Observables

MVVM和ViewModels

model           应用存储的数据,代表业务中的对象和操作,与UI独立
                使用ko,会经常利用ajax读写这些model数据
view model      在ui上数据和操作的代码表现,包括数据List和acid方法
                但这不是ui本身,是纯js对象
view            可见,可交互的ui,展示vm数据,并向vm发送命令,并且更新vm变化的内容
                使用ko,html会被简化,声明式绑定到了vm上,也可以使用模板生成html

创建一个vm

var myViewModel = {
    personName: 'Bob',
    personAge: 123
};

然后,可以使用声明式绑定到view上

The name is <span data-bind="text: personName"></span>

激活ko

ko.applyBindings(myViewModel);

激活ko的代码可以放在html的最底下,或者使用jqeury的

$(function() {
  // Document is ready
});

在调用applyBindings时候,可以指定第二个参数,用来限定vm作用范围,这在多vm时有用

ko.applyBindings(myViewModel, document.getElementById('someElementId'))

Observables

可以使用observables声明vm属性,值变化后会自动通知订阅者

var myViewModel = {
    personName: ko.observable('Bob'),
    personAge: ko.observable(123)
};

不需要改变view,data-bind自动工作
操作

//读取
myViewModel.personName()    
//写入
myViewModel.personName('Mary')
//连续写入
myViewModel.personName('Mary').personAge(50)

如果想自定义订阅变化信息,可以调用subscribe函数

myViewModel.personName.subscribe(function(newValue) {
    alert("The person's new name is " + newValue);
});

subscribe函数接收三个参数:callback,target,event
也可以终止一个subscription
首先捕获返回值,然后调用dispose函数

var subscription = myViewModel.personName.subscribe(function(newValue) { /* do stuff */ });
// ...then later...
subscription.dispose(); // I no longer want notifications

如果想在变化前通知,可以发布给beforeChange事件,比如

myViewModel.personName.subscribe(function(oldValue) {
    alert("The person's previous name is " + oldValue);
}, null, "beforeChange");

设置每次都notify

myViewModel.personName.extend({ notify: 'always' });

延迟或者抑制

myViewModel.personName.extend({ rateLimit: 50 });

Observable Arrays

var myObservableArray = ko.observableArray();    // Initially an empty array
myObservableArray.push('Some value');            // Adds the value and notifies observers

具体例子

<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只是记录array中的objects,而不是它们的状态
可以在初始化时预填充内容

// 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()能获取底层js数组
alert('The length of the array is ' + myObservableArray().length);
alert('The first element is ' + myObservableArray()[0]);

但是推荐使用observableArray自己的方法,因为能维持依赖跟踪

observableArra函数

indexOf返回索引位置

myObservableArray.indexOf('Blah')

slice和js的slice函数一样
函数列表

pop, push, shift, unshift, reverse, sort, splice
remove removeAll
destroy and destroyAll
Delaying and/or suppressing change notifications
push(value)     //在末尾添加一个新的
pop()           //删除最后一个并返回它
unshift(value)  //在前面添加一个新的
shift()         //移除第一个并返回它
reverse()       //返回一个新的observableArray
sort()          //
splice()        //myObservableArray.splice(1, 3)

sort比如

myObservableArray.sort(function (left, right) { 
    return left.lastName == right.lastName ? 0 : (left.lastName < right.lastName ? -1 : 1) 
})

删除

remove(item)    //删除所有值是item的,返回它们得到List
remove( function (item) { return item.age < 18; } ) 
removeAll( ['Chad', 132, undefined] )
removeAll()

destroy会给它们增加一个属性_destroy=ture

destroy( someItem )
destroy( function (someItem) { return someItem.age < 18; } )
destroyAll( ['Chad', 132, undefined] )
destroyAll()

foreach会自动隐藏_destory=ture的元素
延迟或者抑制通知
observableArray会立即通知订阅者,但是如果observableArray变化非常快,而且负担很重,可以限制通知以提高性能

// Ensure it notifies about changes no more than once per 50-millisecond period
myViewModel.myObservableArray.extend({ rateLimit: 50 });
posted @ 2017-03-15 16:00  zhangshihai1232  阅读(190)  评论(0)    收藏  举报