首頁  >  文章  >  web前端  >  在knockoutjs上如何實作flux

在knockoutjs上如何實作flux

亚连
亚连原創
2018-06-20 13:41:001395瀏覽

下面小編就為大家分享一篇在knockoutjs 上自己實現的flux方法,具有很好的參考價值,希望對大家有幫助。一起跟著小編過來看看吧

在knockoutjs 上實作 Flux 單向資料流 狀態機,主要解決多個元件之間對資料的耦合問題。

一、其實簡單

flux的設計理念和實現方案,很大程度上人借鑒和參考了Vuex的實現,只是簡化了某些過程,資料流向圖如下:

在knockoutjs上如何實作flux

從上圖,中以看出資料的改變是單向循環的。我想這就是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。

在knockoutjs上如何實作flux

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程式碼:

<p id="app1">
 app1:
 <span data-bind="text:ko.$store.get(&#39;getName&#39;)"></span>
</p>
<p 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>
</p>
<hr>
<p id="app2">
 app2:
 <ul data-bind="foreach:list" >
  <li data-bind="text:title" ></li>
 </ul>
</p>
<p id="app3">
 app3: 
 <button type="button" data-bind="click:vf.add" >添加</button>
 <span data-bind="text:count"></span>
</p>

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(&#39;setName&#39;, this.name());
 }
}, document.getElementById("app4"));

##四、網域的實例

#########html程式碼:######
<p id="app1">
 <span data-bind="text:name" ></span>
</p>
<p id="app2">
 <span data-bind="text:name"></span>
 <span data-bind="text:full"></span>
 <button type="button" data-bind="click:changeName" >换名</button>
</p>
######js程式碼:######
function rootViewModel(){
 this.name = ko.observable(&#39;root&#39;); 
}
var rVM = new rootViewModel();
flux.createStore({ state: rVM}); //创建root状态器

var treeNode={
 name: ko.observable(&#39;node&#39;),
 changeName:function(){
  ko.$store.areas.treeNode.state.name(&#39;新名字&#39;);
 },
 full: ko.computed(function(){
  //computed的职责:1. 监控其他对象属性的变化,而影响自身对象(flux解决);2. 合并自身对象的几个属性(在function下,有this可解)
  //不能通过ko.$store访问对象本身,因为首次对象本身还没初始化好
  var store = ko.$store;
  //(store.areas.treeNode? store.areas.treeNode.state.name() : &#39;&#39;) 这样也是不行,因为解决第一次通不过,后面肯定不行
  return store.state.name();
 })
}

ko.$store.register(&#39;treeNode&#39;, flux.createStore({ state: treeNode})); //创建子状态机
var app1 = ko.applyBindings(rVM, document.getElementById("app1"));
var app2 = ko.applyBindings(treeNode, document.getElementById("app2"));
###上面是我整理給大家的,希望未來會對大家有幫助。 ######相關文章:#########在nodejs中如何調取微信收貨位址############在nodejs中如何實作微信支付#### #########詳細解讀Vuejs中響應式原理#############使用nodeJS如何實作微信分享######

以上是在knockoutjs上如何實作flux的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn