在knockoutjs 上实现 Flux 单向数据流 状态机,主要解决多个组件之间对数据的耦合问题。
一、其实简单
flux的设计理念和实现方案,很大程度上人借鉴和参考了Vuex的实现,只是简化了某些过程,数据流向图如下:
从上图,中以看出数据的改变是单向循环的。我想这就是Flux理念的核心所在吧。Vuex中对Action规范为Action和Mutation,由action去触发Mutation,action是可以异步的,而Mutation则是同步更新。而我在设计ko的Flux时,去掉了Mutation这个环节,是因为我理解为,异步的请求一般情况下都是与api接口有关系,这块内容存在极大的变化性,应该从业务或项目构架上做一层区分。
二、如果使用
当然,flux只是针对knockoutjs的,所以你使用之前必须引入knockoutjs。flux主要的方法和对象
2.1 静态方法
方法方法,当然他必须先与createStore方法调用。方法是有返回值,他的返回值可以调用register方法注册到指定的域上,但第一次调用此方法时是创建rootStore(根状态器),他不允许被注册到域的。
2.1.1 flux.createStore参数格式
名称方法,方法的第一个参数为state,第二参数开始则为传入的相关内容获取state上的相关状态数据,当然返回是一个ko监控对象。
2.2 实例方法
createStore方法的执行,会在ko实例上增加$store属性,此属性是状态器的实例对象,在任何位置都可以调用他的dispatch来触发事件。
方法注册一个状态域,域与域之间是相互独立存储的,域之间action或get名称是可以重复的调用指定的action,无返回值调用指定的get,有返回值
三、简单的使用
本示例定义了四个ko绑定区域,分别是:app1,app2,app3,app4。实现app4中对name的改变自动影响到app1,而app3对列表的改变自动影响到app2。
3.1 定义vm并初始化store
viewmodel(){
this.list = ko.observableArray();
this.name = ko.observable('无名氏');
this.count = ko.computed(function(){
//必须用this,这个时候ko.$store还没创建完成,应该ko.computed创建时会执行一次此处
//如果是子vm依赖主vm,还是可以用ko.$store的
return this.list().length + '个数'; //需要对监控对象求值,否则computed不能有效
},this);
}
var fullVm = new
viewmodel();
var index = 1;
fullVm.vf={
add: function(){
ko.$store.dispatch('addClass',{title: 'title' + (index++)});
}
}
var opt = {
state: {
class: fullVm
},actions:{
"setName":function(state,name){
state.class.name(name);
},"addClass":function(state,classInfo){
state.class.list.push(classInfo);
}
},getters:{
"getName":function(state){
return state.class.name;
}
}
}
flux.createStore(opt);
根据上述代码,首先定义了viewmodel的一个类,并创建了一个fullVm的一个实例,然后直接在fullVm实例上增加了add方法。
opt的state引用的是fullVm,其中还配置了actions和getters相关对象,然后调用flux.createStore(opt)方法。创建一个store,并关联到ko.$store对象上。
3.2 与视图绑定
HTML代码:
404_74@
404_74@