knockout.js - 如何对包含 json 对象的可观察数组进行排序?
问题描述
您好,我是淘汰 javascript 的新手,我有一个包含 json 对象的 observablearray。所以我试图按给定的顺序对对象列表进行排序。
像 yhis 一样声明 observablearray:
var self =this;
self.array= ko.observableArray();
我用这段代码遍历名为“array”的observablearray:
self.array().forEach(function(v,i){
alert(JSON.stringify(v))
}
它返回我:
{"uuid":"74af2d36-aa47-45c5-af5d-b32c8ed56202","label":"a"}
{"uuid":"412f6222-e4c3-40a0-8a30-b1e31f53d746","label":"b"}
{"uuid":"115c9fa4-c43b-4ad0-bad7-855da850905f","label":"c"}
{"uuid":"55671032-9fc5-4361-8722-3d14abaa7d81","label":"d"}
我真的很想在我的新 observableArray 中加入这样的东西:
{"uuid":"115c9fa4-c43b-4ad0-bad7-855da850905f","label":"c"}
{"uuid":"74af2d36-aa47-45c5-af5d-b32c8ed56202","label":"a"}
{"uuid":"55671032-9fc5-4361-8722-3d14abaa7d81","label":"d"}
{"uuid":"412f6222-e4c3-40a0-8a30-b1e31f53d746","label":"b"}
解决方案
JS排序101
要对数组进行排序,请使用Array.prototype.sort
. 您向它传递一个函数,该函数接受两个项目,a
and b
,并返回1
,-1
或0
。
如果它返回1
if a
come after b
,-1
if a
come before b
,并且0
如果没有区别。
const stringSort = (a, b) => a.localeCompare(b);
const numericSort = (a, b) => a > b ? 1 : a < b ? -1 : 0;
const products = [
{ name: "Bread", cost: 3.10 },
{ name: "Almond Milk", cost: 1.30 },
{ name: "Chocolate", cost: 2.90 }
];
console.log(
"By name:",
products.sort((p1, p2) => stringSort(p1.name, p2.name))
);
console.log(
"By cost:",
products.sort((p1, p2) => numericSort(p1.cost, p2.cost))
);
请注意,您不能将助手直接传递给products.sort
方法!您需要另一个函数来定义我们想要排序的属性。
使用淘汰赛
淘汰赛最酷的地方在于,您可以创建数据的排序版本,该版本会在源更改时自动更新!这是一个交互式示例来展示您可以做什么。
在下面的示例中:
- 我在计算内部排序,以便 UI 的表自动更新
- 添加产品时
- 当您删除产品时
- 当您更改排序方法时
- 当你改变排序方向时
const stringCompare = (a, b) => a.localeCompare(b);
const numericCompare = (a, b) => a > b ? 1 : a < b ? -1 : 0;
const products = ko.observableArray([
{ name: "Bread", cost: 3.10 },
{ name: "Almond Milk", cost: 1.30 },
{ name: "Chocolate", cost: 2.90 }
]);
const sorters = [
{
label: "By cost",
sort: (a, b) => numericCompare(a.cost, b.cost)
},
{
label: "Alphabetically",
sort: (a, b) => stringCompare(a.name, b.name)
}
];
const desc = ko.observable(true);
const sorter = ko.observable(sorters[0]);
const sortMethod = ko.pureComputed(() => desc()
? (a, b) => -1 * sorter().sort(a, b)
: sorter().sort
)
const sortedProducts = ko.pureComputed(() =>
products().sort(sortMethod())
);
const newProduct = {
name: ko.observable(""),
cost: ko.observable(0)
};
const removeProduct = p => {
products.remove(p);
}
const addProduct = () => {
products.push({
name: newProduct.name(),
cost: +newProduct.cost()
});
newProduct.name("");
newProduct.cost(0);
};
ko.applyBindings({ sorters, desc, sortedProducts, newProduct, addProduct, removeProduct })
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div>
Sort by: <select data-bind="options: sorters, value: sorter, optionsText: 'label'"></select>
Descending <input type="checkbox" data-bind="checked: desc">
</div>
<table>
<thead>
<tr>
<th>no.</th>
<th>Name</th>
<th>Cost</th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach: sortedProducts">
<tr>
<td data-bind="text: $index() + 1"></td>
<td data-bind="text: name"></td>
<td data-bind="text: '$' + cost.toFixed(2)"></td>
<td>
<button data-bind="click: $root.removeProduct">remove</button>
</td>
</tr>
</tbody>
<tbody data-bind="with: newProduct">
<tr>
<td></td>
<td>
<input data-bind="value: name" placeholder="product name">
</td>
<td>
<input type="number" min="0" step="0.1" data-bind="value: cost">
</td>
<td>
<button data-bind="click: addProduct">add</button>
</td>
</tr>
</tbody>
</table>
推荐阅读
- r - R使用生成向量的for循环创建新列包含变量的名称
- firebase - 将 Firebase 数据库中的 MapMarker 添加到地图
- r - 在对成对 t 检验执行 reorder_level 之后,有没有办法在折线图中正确定位显着性?
- .net - 基于资源的授权向控制器公开“内部”资源
- html - 如何阻止蒙版图像覆盖 div?
- c++ - c++智能指针c'tor设计说明
- c++ - 如何检查用户输入是否以 0 开头
- python - 在 Pygame 中等待用户输入
- u-boot - u-boot 中的 board_init 函数在哪里调用?
- javascript - 在 Heroku 上部署后未获取数据