KnockoutJS 3.X API 第二章 数据监控(2)监控属性数组
监控属性数组
如果要对一个对象检测和响应变化,会使用监控属性。如果要对一个序列检测并监控变化,需要使用observableArray(监控属性数组)。这在你显示或编辑多个值,需要用户界面的部分反复出现和消失的项目并且具有添加和删除操作的情况下使用observableArray。
例如声明并赋值:
var myObservableArray = ko.observableArray(); // Initially an empty array myObservableArray.push('Some value'); // Adds the value and notifies observers
解如何绑定observableArray到用户界面,让用户可以修改它,可以参考如下例子:
视图代码:
<form data-bind="submit: addItem"> New item: <input data-bind='value: itemToAdd, valueUpdate: "afterkeydown"' /> <button type="submit" data-bind="enable: itemToAdd().length > 0">Add</button> <p>Your items:</p> <select multiple="multiple" width="50" data-bind="options: items"> </select> </form>
视图模型代码:
var SimpleListModel = function(items) { this.items = ko.observableArray(items); this.itemToAdd = ko.observable(""); this.addItem = function() { if (this.itemToAdd() != "") { this.items.push(this.itemToAdd()); // Adds the item. Writing to the "items" observableArray causes any associated UI to update. this.itemToAdd(""); // Clears the text box, because it's bound to the "itemToAdd" observable } }.bind(this); // Ensure that "this" is always this view model }; ko.applyBindings(new SimpleListModel(["Alpha", "Beta", "Gamma"]));
初始化observableArray
如果你希望observableArray在程序开始的时候就具有一定的数据,可以通过如下方式进行observableArray的初始化:
// This observable array initially contains three objects var anotherObservableArray = ko.observableArray([ { name: "Bungle", type: "Bear" }, { name: "George", type: "Hippo" }, { name: "Zippy", type: "Unknown" } ]);
从observableArray读取信息
在后台,一个observableArray实际上是一个监控属性,它的值是一个数组。所以,你可以通过调用获得底层的JavaScript数组不带参数的函数,然后,你可以阅读数组信息。例如:
alert('The length of the array is ' + myObservableArray().length);
alert('The first element is ' + myObservableArray()[0]);
从技术上讲,你可以使用任何的本地JavaScript数组函数来读取observableArray的内容,但通常有一个更好的选择。KO的observableArray有它自己的功能函数,而且用起来更加的方便:
-
在目标浏览器。(例如,本地JavaScript indexOf函数不能在IE 8工作或较早,但KO的indexOf可以兼容任何版本的浏览器。)
-
对于修改数组的内容,如函数push和splice,可以让所有注册的侦听器通知更改,你的用户界面会自动更新KO的依赖跟踪机制所定义的对象。
-
语法是更方便。要调用KO的push方式,只需要写myObservableArray.push(...)。这比调用底层Javascript写方法myObservableArray().push(...)更加方便
索引
该indexOf函数返回等于你参数的第一个数组元素的索引。例如,myObservableArray.indexOf('Blah')将返回第一个数组条目等于从零开始的索引Blah,如果没有匹配值被发现则返回-1
数组片段
observableArray的slice函数与本地JavaScript的slice函数等价(即,它从已有的数组中返回选定的元素)。调用myObservableArray.slice(...)与myObservableArray().slice(...)等效于。
observableArray数组操作
(移除,增加,插入,移除单一元素,反转顺序,排序,移除部分元素)
所有这些功能都等同于运行底层JavaScript数组函数:
-
push( value ) - 增加了一个新的项目,在数组的末尾。
-
pop() - 移除数组的最后一个值,并返回它。
-
unshift( value ) - 在数组开头插入一个新项目。
-
shift() - 移除数组的第一个值并返回。
-
reverse()-反转数组的顺序,并返回observableArray。
-
sort()-排序数组内容并返回observableArray。
-
默认的排序是按字母顺序,但你可以选择传递一个参数来控制阵列如何进行排序。你的函数应该接受来自数组的任意两个对象,如果第一个参数为较小返回一个负值,正值是第二较小,或为零它们视为相等。例如,排序按姓氏'人'对象的数组,你可以写myObservableArray.sort(function (left, right) { return left.lastName == right.lastName ? 0 : (left.lastName < right.lastName ? -1 : 1) })
-
-
splice()-删除,并返回从一个给定的索引起始元件的给定数目。例如,myObservableArray.splice(1, 3)将删除索引位置1(即第二,第三和第四个元素)开始三个元素,并返回它们作为一个数组。
有关这些详细信息observableArray的函数,可以参考等价文档标准的JavaScript数组函数。
删除和删除全部
observableArray 的补充方法:
-
remove( someItem )-移除等于someItem值的元素并返回它们作为一个数组。
-
remove( function (item) { return item.age < 18; } )-删除其所有的价值age小于18的元素,将它们作为一个数组。
-
removeAll( ['Chad', 132, undefined] )-移除所有等于'Chad'或123或undefined的元素并返回它们作为一个数组。
-
removeAll() - 删除所有值并返回它们作为一个数组。
销毁destroyAll(注: Ruby on Rails的开发人员需要了解)
该destroy和destroyAll函数主要目的是为使用Ruby on Rails开发者更加便利:
-
destroy( someItem )-查找值等于someItem数组中的任何元素,并为特殊的属性_destroy赋值true。
-
destroy( function (someItem) { return someItem.age < 18; } )-在数组中查找任何对象age小于18的元素,并为特殊的属性_destroy赋值true。
-
destroyAll( ['Chad', 132, undefined] )-找到数组中所有等于'Chad'或123或undefined的元素,并为特殊的属性_destroy赋值true。
-
destroyAll()-对数组中所有对象的特殊的属性_destroy赋值true。
那么,这是什么_destroy东西一回事呢?Rails开发者。在Rails中的约定是,当你传递到一个动作或一个JSON对象,该框架可以自动将其转换为一个ActiveRecord对象,然后将其保存到数据库中。它知道它的对象都已经在你的数据库,并发出正确的INSERT或UPDATE语句。告诉框架删除一条记录,你只是将_destroy标记设置为true。
请注意,当KO呈现一个foreach具有约束性,它会自动隐藏标记用任何元素的_destroy。所以,你可以有某种"删除"按钮调用该destroy(someItem)方法在数组上,这将立即引起指定的项目,从UI消失。后来,当您提交Rails的JSON对象,该项目也将被从数据库中删除。
延缓和/或抑制更改通知
通常情况下,observableArray只要它的改变会立即通知其用户。但如果observableArray反复更改高昂的更新数据传输频率,你可以通过限制或拖延更改通知,获得更好的性能。这是通过使用rateLimit进行限制:
// Ensure it notifies about changes no more than once per 50-millisecond period myViewModel.myObservableArray.extend({ rateLimit: 50 });