<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      代碼改變世界

      Omi框架Store體系的前世今生

      2017-03-23 10:13  【當耐特】  閱讀(1662)  評論(4)    收藏  舉報

      原文鏈接-https://github.com/AlloyTeam/omi

      Store 體系

      先說說Store系統是干什么的!為什么要造這樣一個東西?能夠系統架構帶來什么?

      當我們組件之間,擁有共享的數據的時候,經常需要進行組件通訊。在Omi框架里,父組件傳遞數據給子組件非常方便:

      • 通過在組件上聲明 data-* 或者 :data-* 傳遞給子節點
      • 通過在組件上聲明 data 或者 :data 傳遞給子節點 (支持復雜數據類型的映射)
      • 聲明 group-data 把數組里的data傳給一堆組件傳遞(支持復雜數據類型的映射)

      注:上面帶有冒號的是傳遞javascript表達式

      通過聲明onXxx="xxxx"可以讓子組件內執行父組件的方法。具體的如下圖所示:

      如果還不明白的話,那... 我就直接上代碼了:

      class Main extends Omi.Component {
      
          handlePageChange(index){
              this.content.goto(index+1)
              this.update()
          }
      
          render () {
              return `<div>
                          <h1>Pagination Example</h1>
                          <Content name="content" />
                          <Pagination
                              name="pagination"
                              :data-total="100"
                              :data-page-size="10"
                              :data-num-edge="1"
                              :data-num-display="4"     
                              onPageChange="handlePageChange" />
                      </div>`;
          }
      }
      

      上面的例子中,

      • 父組件的render方法里,通過 data-? 傳遞數據給子組件 Pagination
      • 通過onPageChange="handlePageChange"實現子組件與父組件通訊

      詳細代碼可以點擊: 分頁例子地址

      當然你也可以使用event emitter / pubsub庫在組件之間通訊,比如這個只有 200b 的超小庫mitt 。但是需要注意mitt兼容到IE9+,Omi兼容IE8。但是,使用event emitter / pubsub庫會對組件代碼進行入侵,所以非常不建議在基礎非業務組件使用這類代碼庫。

      雖然組件通訊非常方便,但是在真實的業務場景中,不僅僅是父子、爺孫、爺爺和堂兄、嫂子和堂弟...
      onXxx="xxxx"就顯得無能為力,力不從心了,各種數據傳遞、組件實例互操作、 emitter/pubsub或者循環依賴,讓代碼非常難看且難以維護。所以:

      Omi.Store是用來管理共享數據以及共享數據的邏輯 。
      

      Omi Store使用足夠簡便,對架構入侵性極極極小(3個極代表比極小還要小)。下面一步一步從todo的例子看下Store體系怎么使用。

      定義 Omi.Store

      Omi.Store是基類,我們可以繼承Omi.Store來定義自己的Store,比如下面的TodoStore。

      import Omi from 'omi'
      
      class TodoStore extends Omi.Store {
          constructor(data , isReady) {
              super(isReady)
      
              this.data = Object.assign({
                  items:[],
                  length:0
              },data)
      
              this.data.length = this.data.items.length
          }
      
          add(value){
              this.data.items.push(value)
              this.data.length = this.data.items.length
              this.update()
          }
      
          clear(){
              this.data.items.length = 0
              this.data.length = 0
              this.update()
          }
      }
      
      export default TodoStore
      

      TodoStore定義了數據的基本格式和數據模型的邏輯。
      比如 this.data 就是數據的基本格式:

      {
          items:[],
          length:0
      }
      

      add和clear就是共享數據相關的邏輯。

      值得注意的是,在add和clear方法里都有調用this.update();這個是用來更新組件的,this.update并不會更新所有組件。但是他到底會更新哪些組件呢?等講到store的addView方法你就明白了。

      創建 Omi.Store

      通過 new 關鍵字來使用TodoStore對象的實例。

      let store = new TodoStore({ /* 初始化數據 */ ,/* 數據是否準備好 */  })
      

      上面可以傳入一些初始化配置信息,store里面便包含了整個應用程序共享的狀態數據以及貢獻數據邏輯方法(add,clear)。

      當然,這些初始化配置信息可能是異步拉取的。所以,有兩種方法解決異步拉取store配置的問題:

      • 拉取數據,然后new TodoStore(),再Omi.render
      • 先let store = new TodoStore(),再Omi.render,組件內部監聽store.ready,拉取數據更改store的data信息,然后執行store.beReady()

      根組件注入 store

      為了讓組件樹能夠使用到 store,可以通過Omi.render的第三個參數給根組件注入 store:

      Omi.render(new Todo(),'body',{
          store: store
      });
      

      當然ES2015已經允許你這樣寫了:

      Omi.render(new Todo(),'body',{
          store
      });
      

      兩份代碼同樣的效果。

      通過Omi.render注入之后,在組件樹的所有組件都可以通過 this.$store 訪問到 store。

      利用 beforeRender

      為什么要說beforeRender這個函數? 因為通過beforeRender轉換store的data到組件的data,這樣store的數據和組件的數據就解耦開了。

      beforeRender是生命周期的一部分。且看下面這張圖:

      beforeRender

      不管是實例化或者存在期間,在render之前,會去執行beforeRender方法。所以可以利用該方法寫store的data到組件data的轉換邏輯。比如:

      import Omi from '../../src/index.js';
      import List from './list.js';
      
      Omi.makeHTML('List', List);
      
      class Todo extends Omi.Component {
          constructor(data) {
              super(data)
          }
      
          install(){
              this.$store.addView(this)
          }
      
          beforeRender(){
              this.data.length = this.$store.data.items.length
          }
      
          add (evt) {
              evt.preventDefault()
              let value = this.data.text
              this.data.text = ''
              this.$store.add(value)
          }
      
          style () {
              return `
              h3 { color:red; }
              button{ color:green;}
              `;
          }
      
          clear(){
              this.data.text = ''
              this.$store.clear()
          }
      
          handleChange(evt){
              this.data.text = evt.target.value
          }
      
          render () {
              return `<div>
                          <h3>TODO</h3>
                          <button onclick="clear">Clear</button>
                          <List name="list" data="$store.data" />
                          <form onsubmit="add" >
                              <input type="text" onchange="handleChange"  value="{{text}}"  />
                              <button>Add #{{length}}</button>
                          </form>
      
                      </div>`;
          }
      }
      
      export default Todo;
      

      為什么要去寫beforeRender方法?因為render只會使用this.data去渲染頁面而不會去使用this.$store.data,所以需要把數據轉移到組件的this.data下。這樣組件既能使用自身的data,也能使用全局放this.$store.data了,不會耦合在一起。

      注意看上面的:

          install(){
              this.$store.addView(this)
          }
      

      通過 addView 可以讓 store 和 view(也就是組件的實例) 關聯起來,以后store執行update方法的時候,關聯的view都會自動更新!

      再看上面的子組件聲明:

      <List name="list" data="$store.data" />
      

      這樣相當于把this.$store.data傳遞給了List組件。所以在List內部,就不再需要寫beforeRender方法轉換了。

      class List extends Omi.Component {
          constructor(data) {
              super(data)
          }
      
          render () {
              return ` <ul> {{#items}} <li>{{.}}</li> {{/items}}</ul>`
          }
      }
      
      這里需要特別強調,不需要把所有的數據提取到store里,只提取共享數據就好了,組件自身的數據還是放在組件自己進行管理。
      

      異步數據

      通常,在真實的業務需求中,數據并不是馬上能夠拿到。所以這里模擬的異步拉取的todo數據:

      let todoStore = new TodoStore()
      setTimeout(()=>{
          todoStore.data.items = ["omi","store"];
          todoStore.data.length = todoStore.data.items.length
          todoStore.beReady();
      },2000)
      

      上面的beReady就是代碼已經準備就緒,在組件內部可以監聽ready方法:

      class Todo extends Omi.Component {
          constructor(data) {
              super(data)
          }
      
          install(){
              this.$store.addView(this)
          }
      
          installed(){
              this.$store.ready(()=>this.$store.update())
          }
          
          add (evt) {
              evt.preventDefault()
              if(!this.$store.isReady){
                  return
              }
              let value = this.data.text
              this.data.text = ''
              this.$store.add(value)
          }
      

      可以看到上面的add方法可以通過this.$store.isReady獲取組件store是否準備就緒。

      源碼地址

      相關

      主站蜘蛛池模板: 国产精品理论片| 欧美一本大道香蕉综合视频| 久在线精品视频线观看| 色吊丝二区三区中文写幕| 亚洲精品一二三四区| 国产精品美女黑丝流水| 九九久久人妻精品一区色| 免费午夜无码片在线观看影院| 少妇被粗大的猛烈进出69影院一 | 午夜福利国产精品小视频| 美女内射无套日韩免费播放| 肉色丝袜足j视频国产| 真实单亲乱l仑对白视频| 日韩人妻少妇一区二区三区| 99人体免费视频| 国产99视频精品免费专区| 丰满的少妇一区二区三区| 激情视频乱一区二区三区| 性做久久久久久久| 亚洲精品不卡av在线播放| 国产av黄色一区二区三区| 狠狠色狠狠综合久久| 成在线人视频免费视频| 成人精品国产一区二区网| 国产大学生粉嫩无套流白浆| 国产精品亚洲综合一区二区| 5D肉蒲团之性战奶水欧美| 二连浩特市| 视频一区二区不中文字幕| 女人的天堂A国产在线观看| 国产精品视频一区二区噜噜| 九九色这里只有精品国产| 极品少妇被后入内射视| 成人欧美日韩一区二区三区| 国产AV影片麻豆精品传媒| 一本久道久久综合久久鬼色| 在线天堂中文www官网| 亚洲中文字字幕精品乱码| 九九热视频在线观看精品| 毛茸茸性xxxx毛茸茸毛茸茸| 精品人妻蜜臀一区二区三区|