knockout在不同ViewModel之间的通讯

构建复杂应用,view-model之间的通讯是非常重要的一个环节,此过程的方便与否,组件之间的严格隔离与否,直接影响健壮性和开发禅道心情。

本文会:

  1. 介绍knockout.js自带的事件收发;
  2. 一个简单扩展实现 ViewModel之间 数据同步(或者叫数据捆绑);

 一:Knockout的事件收发

抽象的理解:建立一个公开的无线电塔,任何viewmodel可以在某个频道广播信息,其他正在收听的viewmodel,只要频道对的上,那么就能收听到对应信息

var radioTower = new ko.subscribable(); //创建一个无线电塔

收听者用法:

 //三个参数依次为收到的信息callback、目标viewModel(可选)、频道名称(可选)
radioTower.subscribe(callback, target, channel);
//收听者的俩个例子
radioTower.subscribe(function(newValue) { this.latestTopic(newValue);}, vm, "mytopic");
radioTower.subscribe(function(newData) {
    console.log("收到新数据:",newData);
}, null, "changeLength");

发送者的用法:

//两个参数依次为想发送的数据、频道名称
radioTower.notifySubscribers(data, channel);
//真实的例子
//接收者
radioTower.subscribe(function(newValue) {
    this.latestTopic(newValue);
}, vm, "mytopic");
//发送者
radioTower.notifySubscribers("MayDay MayDay!", "changeLength");

二:一个小扩展来更方便的实现数据同步

扩展代码:

;(function(ko){
    var radioTower = new ko.subscribable();

    ko.subscribable.fn.pub = function(topic) {
        this.subscribe(function(newValue) {
            radioTower.notifySubscribers(newValue, topic);
        });
        return this; //support chaining
    };
    ko.subscribable.fn.sub = function(topic,call,vm) {
        var target = vm || null;
        var cb = call || this; //如果没有call,那么直接捆绑原始数据
        radioTower.subscribe(cb, target, topic);

        return this;  //support chaining
    };
})(ko);

用法:

viewModel-A中:
//监听数组,当数组变化时在“ulist”频道里发送list这个数据
this.list = ko.observableArray([]).pub("ulist");
viewModel-B中:
this.list2 = ko.observableArray([]);
this.list2.sub("ulist"); //收听"ulist",当viewModel-A中的list改变时,它也会跟着变

//如果不想直接绑定,比如这里实现viewModel-A中的ulist的长度 和 viewModel-B中的length同步:
self.length = ko.observable(0);
self.length.sub("ulist",function(val){
    self.length(val.length);
});//第二个可选参数为回调

源代码例子

发表评论

电子邮件地址不会被公开。