服务类小程序流程制做_在knockoutjs 上自己完成的

在knockoutjs 上自己实现的flux(实例讲解)       下面小编就为大家分享一篇在knockoutjs 上自己实现的flux方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

在knockoutjs 上实现 Flux 单向数据流 状态机,主要解决多个组件之间对数据的耦合问题。

一、其实简单

flux的设计理念和实现方案,很大程度上人借鉴和参考了Vuex的实现,只是简化了某些过程,数据流向图如下:

从上图,中以看出数据的改变是单向循环的。我想这就是Flux理念的核心所在吧。Vuex中对Action规范为Action和Mutation,由action去触发Mutation,action是可以异步的,而Mutation则是同步更新。而我在设计ko的Flux时,去掉了Mutation这个环节,是因为我理解为,异步的请求一般情况下都是与api接口有关系,这块内容存在极大的变化性,应该从业务或项目构架上做一层区分。

二、如果使用

当然,flux只是针对knockoutjs的,所以你使用之前必须引入knockoutjs。flux主要的方法和对象

2.1 静态方法


flux.createStore 创建一个store(状态器)实例,当然此方法是有返回值,他的返回值可以调用register方法注册到指定的域上,但第一次调用此方法时是创建rootStore(根状态器),他不允许被注册到域的。
actions 更改state上的状态方法,方法的第一个参数为state,第二参数开始则为传入的相关内容

2.2 实例方法

createStore方法的执行,会在ko实例上增加$store属性,此属性是状态器的实例对象,在任何位置都可以调用他的dispatch来触发事件。


register 创建和注册一个状态域,域与域之间是相互独立存储的,域之间action或get名称是可以重复的

三、简单的使用

本示例定义了四个ko绑定区域,分别是:app1, app2, app3, app4。实现app4中对name的改变自动影响到app1,而app3对列表的改变自动影响到app2。

3.1 定义vm并初始化store

function ViewModel(){
 this.list = ko.observableArray();
 this.name = ko.observable('无名氏');
 this.count = ko.computed(function(){
 //必须用this,这个时候ko.$puted创建时会执行一次此处
 //如果是子vm依赖主vm,还是可以用ko.$store的
 return this.list().length + '个数'; //puted不能有效
 },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代码:

 div id="app1" 
 app1:
 span data-bind="text:ko.$store.get('getName')" /span 
 /div 
 div id="app4" 
 app4:
 input type="text" data-bind="value:name" / 
 button type="text" data-bind="click:changeName" 改变名字 /button 
 span data-bind="text:ko.$store.state.class.name" /span 
 /div 
 div id="app2" 
 app2:
 ul data-bind="foreach:list" 
 li data-bind="text:title" /li 
 /ul 
 /div 
 div id="app3" 
 app3: 
 button type="button" data-bind="click:vf.add" 添加 /button 
 span data-bind="text:count" /span 
 /div 

js代码:

var app1 = ko.applyBindings(fullVm, document.getElementById("app1"));
var app2 = ko.applyBindings(fullVm, document.getElementById("app2"));
var app3 = ko.applyBindings(fullVm, document.getElementById("app3"));
//测试两个vm之间的依赖 解藕
var app4 = ko.applyBindings({
 name: ko.observable(),
 changeName:function(data,event){
 ko.$store.dispatch('setName', this.name());
}, document.getElementById("app4"));

四、域的实例

html代码:

 div id="app1" 
 span data-bind="text:name" /span 
 /div 
 div id="app2" 
 span data-bind="text:name" /span 
 span data-bind="text:full" /span 
 button type="button" data-bind="click:changeName" 换名 /button 
 /div 

js代码:

function rootViewModel(){
 this.name = ko.observable('root'); 
var rVM = new rootViewModel();
flux.createStore({ state: rVM}); //创建root状态器
var treeNode={
 name: ko.observable('node'),
 changeName:function(){
 ko.$store.areas.treeNode.state.name('新名字');
 full: ko.computed(function(){
 //computed的职责:1. 监控其他对象属性的变化,而影响自身对象(flux解决);2. 合并自身对象的几个属性(在function下,有this可解)
 //不能通过ko.$store访问对象本身,因为首次对象本身还没初始化好
 var store = ko.$store;
 //(store.areas.treeNode store.areas.treeNode.state.name() : '') 这样也是不行,因为解决第一次通不过,后面肯定不行
 return store.state.name();
ko.$store.register('treeNode', flux.createStore({ state: treeNode})); //创建子状态机
var app1 = ko.applyBindings(rVM, document.getElementById("app1"));
var app2 = ko.applyBindings(treeNode, document.getElementById("app2"));

五、其他

当然模块化的引用,也是支持。具体实例细节可参考test中的测试示例。

以上这篇在knockoutjs 上自己实现的flux(实例讲解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持凡科。


内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://zmjldkxcx.cn/ziyuan/3185.html