在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.use | 在require模式下,将flux与ko做关联的方法,当然他必须先与createstore方法调用。 |
flux.createstore | 创建一个store(状态器)实例,当然此方法是有返回值,他的返回值可以调用register方法注册到指定的域上,但第一次调用此方法时是创建rootstore(根状态器),他不允许被注册到域的。 |
2.1.1 flux.createstore参数格式
参数名称 | 说明 |
state | 状态器相关状态数据 |
actions | 更改state上的状态方法,方法的第一个参数为state,第二参数开始则为传入的相关内容 |
getters | 获取state上的相关状态数据,当然返回是一个ko监控对象。 |
2.2 实例方法
createstore方法的执行,会在ko实例上增加$store属性,此属性是状态器的实例对象,在任何位置都可以调用他的dispatch来触发事件。
方法 | 说明 |
register | 创建和注册一个状态域,域与域之间是相互独立存储的,域之间action或get名称是可以重复的 |
unregister | 移除一个状态域 |
dispatch | 根据actionname调用指定的action,无返回值 |
get | 根据getname调用指定的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.$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代码:
<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> <hr> <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中的测试示例。
项目的git地址:,欢迎大家指正和提出宝贵的意见。
以上这篇在knockoutjs 上自己实现的flux(实例讲解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
推荐阅读
-
在knockoutjs 上自己实现的flux(实例讲解)
-
怎样在IE上显示自己的名字?简单几步轻松实现
-
怎样在IE上显示自己的名字?简单几步轻松实现
-
docker在linux上的安装部署实例讲解
-
【从零开始搭建自己的.NET Core Api框架】(三)集成轻量级ORM——SqlSugar:3.2 在框架的基础上利用SqlSugar快速实现CRUD实战篇
-
docker在linux上的安装部署实例讲解
-
在knockoutjs上如何实现flux
-
【从零开始搭建自己的.NET Core Api框架】(三)集成轻量级ORM——SqlSugar:3.2 在框架的基础上利用SqlSugar快速实现CRUD实战篇
-
在knockoutjs 上自己实现的flux(实例讲解)
-
Mycat读写分离在MySQL主从复制基础上实现的实例