监控数组(Observable Arrays)
如果你要探测和响应一个对象的变化,你应该用observables。如果你需要探测和响应一个集合对象的变化,你应该用 observableArray
。在很多场景下,它都非常有用,比如你要在UI上需要显示/编辑的一个列表数据集合,然后对集合进行添加和删除。
例子
var myObservableArray = ko.observableArray(); // Initially an empty array myObservableArray.push('Some value'); // Adds the value and notifies observers
这里需要单独提示一点对Observable Array理解可能出现偏差的地方:
-
Observable Array不监控元素本身的变化:Observable Array只处理元素个数的变化,比如数组元素删除和添加。元素自身的变化是否能自动监控,取决于元素本身是普通对象还是Observable对象。
-
如何既监控数组元素个数,又监控元素内容变化:往数组中push元素的时候,使用observable元素即可,则该元素可以自动监控自身的变化。
预加载一个监控数组(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
其实就是一个 observable的监控对象,只不过他的值是一个数组 (observableArray
还加了很多其他特性,稍后介绍)。所以你可以像获取普通的 observableArray
的值一样,只需要调用无参函数就可以获取自身的值了。 例如,你可以像下面这样获取它的值:
alert('The length of the array is ' + myObservableArray().length); alert('The first element is ' + myObservableArray()[0]);
理论上你可以使用任何原生的JavaScript数组函数来操作这些数组,但是KO提供了更好的功能等价函数observableArray
,他们非常有用是因为:
-
兼容所有浏览器。(例如
indexOf
不能在IE8和早期版本上使用,但KO自己的indexOf
可以在所有浏览器上使用) -
在数组操作函数方面(例如
push
andsplice
),KO自己的方式可以自动触发依赖跟踪,并且通知所有的订阅者它的变化,然后让UI界面也相应的自动更新。 -
语法更方便,调用KO的
push
方法,只需要这样写:myObservableArray.push(...)
。 比如原生数组的myObservableArray().push(...)
好用多了。
下面讲解的均是 observableArray
的读取和写入的相关函数。
indexOf
indexOf
函数返回的是第一个等于你参数数组项的索引。例如: myObservableArray.indexOf('Blah')
将返回以0为第一个索引的第一个等于 Blah
的数组项的索引。如果没有找到相等的,将返回 -1
。
slice
slice
函数是 observableArray
相对于JavaScript 原生函数 slice
的等价函数(返回给定的从开始索引到结束索引之间所有的对象集合)。 调用 myObservableArray.slice(...)
等价于调用JavaScript原生函数myObservableArray().slice(...)
)。
操作observableArray
observableArray
展现的是数组对象相似的函数并通知订阅者的功能。
pop, push, shift, unshift, reverse, sort, splice
所有这些函数都是和JavaScript数组原生函数等价的,唯一不同的数组改变可以通知订阅者:
-
myObservableArray.push('Some new value')
在数组末尾添加一个新项 -
myObservableArray.pop()
删除数组最后一个项并返回该项 -
myObservableArray.unshift('Some new value')
在数组头部添加一个项 -
myObservableArray.shift()
删除数组头部第一项并返回该项 -
myObservableArray.reverse()
翻转整个数组的顺序myObservableArray.reverse()
reverses the order of the array -
myObservableArray.sort()
给数组排序myObservableArray.sort()
sorts the array contents. - 默认情况下,是按照字符排序(如果是字符)或者数字排序(如果是数字)。
-
你可以排序传入一个排序函数进行排序,该排序函数需要接受2个参数(代表该数组里需要比较的项),如果第一个项小于第二个项,返回-1,大于则返回1,等于返回0。例如:用lastname给person排序,你可以这样写:
myObservableArray.sort(function(left, right) { return left.lastName == right.lastName ? 0 : (left.lastName < right.lastName ? -1 : 1) })
-
myObservableArray.splice()
删除指定开始索引和指定数目的数组对象元素。例如myObservableArray.splice(1, 3)
从索引1开始删除3个元素(第2,3,4个元素)然后将这些元素作为一个数组对象返回。
更多observableArray 函数的信息,请参考等价的 standard JavaScript array functions。
remove 和 removeAll
observableArray
添加了一些JavaScript数组默认没有但非常有用的函数:
-
myObservableArray.remove(someItem)
删除所有等于someItem
的元素并将被删除元素作为一个数组返回 -
myObservableArray.remove(function(item) { return item.age < 18 })
删除所有age
属性小于18的元素并将被删除元素作为一个数组返回 -
myObservableArray.removeAll(['Chad', 132, undefined])
删除所有等于'Chad'
,123
, orundefined
and returns them as an array
destroy和destroyAll(注:通常只和Ruby on Rails开发者有关)
destroy
和 destroyAll
函数是为Ruby on Rails开发者方便使用为开发的:
-
myObservableArray.destroy(someItem)
找出所有等someItem
的元素并给他们添加一个属性_destroy
,并赋值为true
-
myObservableArray.destroy(function(someItem) { return someItem.age < 18 })
找出所有age
属性小于18的元素并给他们添加一个属性_destroy
,并赋值为true
-
myObservableArray.destroyAll(['Chad', 132, undefined])
找出所有等于'Chad'
,123
, orundefined
的元素并给他们添加一个属性_destroy
,并赋值为true
那么, _destroy
是做什么用的?正如我提到的,这只是为Rails 开发者准备的。在Rails 开发过程中,如果你传入一个JSON对象,Rails 框架会自动转换成ActiveRecord对象并且保存到数据库。Rails 框架知道哪些对象以及在数据库中存在,哪些需要添加或更新, 标记 _destroy
为 true
就是告诉框架删除这条记录。
注意的是:在KO render一个 foreach
模板的时候,会自动隐藏带有 _destroy
属性并且值为 true
的元素。所以如果你的“delete”按钮调用 destroy(someItem)
方法的话,UI界面上的相对应的元素将自动隐藏,然后等你提交这个JSON对象到Rails上的时候,这个元素项将从数据库删除(同时其它的元素项将正常的插入或者更新)。