构建复杂应用,view-model之间的通讯是非常重要的一个环节,此过程的方便与否,组件之间的严格隔离与否,直接影响健壮性和开发禅道心情。
本文会:
- 介绍knockout.js自带的事件收发;
- 一个简单扩展实现 ViewModel之间 数据同步(或者叫数据捆绑);
一:Knockout的事件收发
抽象的理解:建立一个公开的无线电塔,任何viewmodel可以在某个频道广播信息,其他正在收听的viewmodel,只要频道对的上,那么就能收听到对应信息
var radioTower = new ko.subscribable(); //创建一个无线电塔
收听者用法:
//三个参数依次为收到的信息callback、目标viewModel(可选)、频道名称(可选)
radioTower.subscribe(callback, target, channel);
radioTower.subscribe(callback, target, channel);
//收听者的俩个例子
radioTower.subscribe(function(newValue) { this.latestTopic(newValue);}, vm, "mytopic");
radioTower.subscribe(function(newData) {
console.log("收到新数据:",newData);
}, null, "changeLength");
radioTower.subscribe(function(newValue) { this.latestTopic(newValue);}, vm, "mytopic");
radioTower.subscribe(function(newData) {
console.log("收到新数据:",newData);
}, null, "changeLength");
发送者的用法:
//两个参数依次为想发送的数据、频道名称
radioTower.notifySubscribers(data, channel);
radioTower.notifySubscribers(data, channel);
//真实的例子
//接收者
radioTower.subscribe(function(newValue) {
this.latestTopic(newValue);
}, vm, "mytopic");
//接收者
radioTower.subscribe(function(newValue) {
this.latestTopic(newValue);
}, vm, "mytopic");
//发送者
radioTower.notifySubscribers("MayDay MayDay!", "changeLength");
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);
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");
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);
});//第二个可选参数为回调
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);
});//第二个可选参数为回调