小程序解決方案 Westore - 組件、純組件、插件開發

數據流轉

先上一張圖看清 Westore 怎麼解決小程序數據難以管理和維護的問題:html

非純組件的話,能夠直接省去 triggerEvent 的過程,直接修改 store.data 而且 update,造成縮減版單向數據流。git

Github: https://github.com/dntzhang/westoregithub

組件

這裏說的組件即是自定義組件,使用原生小程序的開發格式以下:編程

Component({
  properties: { },

  data: { },

  methods: { }
})

使用 Westore 以後:json

import create from '../../utils/create'

create({
  properties: { },

  data: { },

  methods: { }
})

看着差異不大,可是區別:小程序

  • Component 的方式使用 setData 更新視圖
  • create 的方式直接更改 store.data 而後調用 update
  • create 的方式可使用函數屬性,Component 不能夠,如:
export default {
  data: {
    firstName: 'dnt',
    lastName: 'zhang',
    fullName:function(){
      return this.firstName + this.lastName
    }
  }
}

綁定到視圖:網絡

<view>{{fullName}}</view>

小程序 setData 的痛點:dom

  • 使用 this.data 能夠獲取內部數據和屬性值,但不要直接修改它們,應使用 setData 修改
  • setData 編程體驗很差,不少場景直接賦值更加直觀方便
  • setData 卡卡卡慢慢慢,JsCore 和 Webview 數據對象來回傳浪費計算資源和內存資源
  • 組件間通信或跨頁通信會把程序搞得亂七八糟,變得極難維護和擴展

沒使用 westore 的時候常常能夠看到這樣的代碼:ide

使用完 westore 以後:函數

上面兩種方式也能夠混合使用。

能夠看到,westore 不只支持直接賦值,並且 this.update 兼容了 this.setData 的語法,但性能大大優於 this.setData,再舉個例子:

this.store.data.motto = 'Hello Westore'
this.store.data.b.arr.push({ name: 'ccc' })
this.update()

等同於

this.update({
  motto:'Hello Westore',
  [`b.arr[${this.store.data.b.arr.length}]`]:{name:'ccc'}
})

這裏須要特別強調,雖然 this.update 能夠兼容小程序的 this.setData 的方式傳參,可是更加智能,this.update 會先 Diff 而後 setData。原理:

純組件

常見純組件由不少,如 tip、alert、dialog、pager、日曆等,與業務數據無直接耦合關係。
組件的顯示狀態由傳入的 props 決定,與外界的通信經過內部 triggerEvent 暴露的回調。
triggerEvent 的回調函數能夠改變全局狀態,實現單向數據流同步全部狀態給其餘兄弟、堂兄、姑姑等組件或者其餘頁面。

Westore裏可使用 create({ pure: true }) 建立純組件(固然也能夠直接使用 Component),好比 :

import create from '../../utils/create'

create({
  pure : true,
  
  properties: {
    text: {
      type: String,
      value: '',
      observer(newValue, oldValue) { }
    }
  },

  data: {
    privateData: 'privateData'
  },

  ready: function () {
    console.log(this.properties.text)
  },

  methods: {
    onTap: function(){
      this.store.data.privateData = '成功修改 privateData'
      this.update()
      this.triggerEvent('random', {rd:'成功發起單向數據流' + Math.floor( Math.random()*1000)})
    }
  }
})

須要注意的是,加上 pure : true 以後就是純組件,組件的 data 不會被合併到全局的 store.data 上。

組件區分業務組件和純組件,他們的區別以下:

  • 業務組件與業務數據緊耦合,換一個項目可能該組件就用不上,除非很是相似的項目
  • 業務組件經過 store 得到所需參數,經過更改 store 與外界通信
  • 業務組件也能夠經過 props 得到所需參數,經過 triggerEvent 與外界通信
  • 純組件與業務數據無關,可移植和複用
  • 純組件只能經過 props 得到所需參數,經過 triggerEvent 與外界通信

大型項目必定會包含純組件、業務組件。經過純組件,能夠很好理解單向數據流。

小程序插件

小程序插件是對一組 JS 接口、自定義組件或頁面的封裝,用於嵌入到小程序中使用。插件不能獨立運行,必須嵌入在其餘小程序中才能被用戶使用;而第三方小程序在使用插件時,也沒法看到插件的代碼。所以,插件適合用來封裝本身的功能或服務,提供給第三方小程序進行展現和使用。

插件開發者能夠像開發小程序同樣編寫一個插件並上傳代碼,在插件發佈以後,其餘小程序方可調用。小程序平臺會託管插件代碼,其餘小程序調用時,上傳的插件代碼會隨小程序一塊兒下載運行。

插件開發

Westore 提供的目錄以下:

|--components
|--westore  
|--plugin.json  
|--store.js

建立插件:

import create from '../../westore/create-plugin'
import store from '../../store'

//最外層容器節點須要傳入 store,其餘組件不傳 store
create(store, {
  properties:{
    authKey:{
      type: String,
      value: ''
    }
  },
  data: { list: [] },
  attached: function () {
    // 能夠獲得插件上聲明傳遞過來的屬性值
    console.log(this.properties.authKey)
    // 監聽全部變化
    this.store.onChange = (detail) => {
      this.triggerEvent('listChange', detail)
    }
    // 能夠在這裏發起網絡請求獲取插件的數據
    this.store.data.list = [{
      name: '電視',
      price: 1000
    }, {
      name: '電腦',
      price: 4000
    }, {
      name: '手機',
      price: 3000
    }]

    this.update()

    //一樣也直接和兼容 setData 語法
    this.update(
        { 'list[2].price': 100000 }
    )
  }
})

在你的小程序中使用組件:

<list auth-key="{{authKey}}" bind:listChange="onListChange" />

這裏來梳理下小程序自定義組件插件怎麼和使用它的小程序通信:

  • 經過 properties 傳入更新插件,經過 properties 的 observer 來更新插件
  • 經過 store.onChange 收集 data 的全部變動
  • 經過 triggerEvent 來拋事件給使用插件外部的小程序

這麼方便簡潔還不趕忙試試 Westore插件開發模板

特別強調

插件內全部組件公用的 store 和插件外小程序的 store 是相互隔離的。

原理

頁面生命週期函數

名稱 描述
onLoad 監聽頁面加載
onShow 監聽頁面顯示
onReady 監聽頁面初次渲染完成
onHide 監聽頁面隱藏
onUnload 監聽頁面卸載

組件生命週期函數

名稱 描述
created 在組件實例進入頁面節點樹時執行,注意此時不能調用 setData
attached 在組件實例進入頁面節點樹時執行
ready 在組件佈局完成後執行,此時能夠獲取節點信息(使用 SelectorQuery )
moved 在組件實例被移動到節點樹另外一個位置時執行
detached 在組件實例被從頁面節點樹移除時執行

因爲開發插件時候的組件沒有 this.page,因此 store 是從根組件注入,並且能夠在 attached 提早注入:

export default function create(store, option) {
    let opt = store
    if (option) {
        opt = option
        originData = JSON.parse(JSON.stringify(store.data))
        globalStore = store
        globalStore.instances = []
        create.store = globalStore
    }

    const attached = opt.attached
    opt.attached = function () {
        this.store = globalStore
        this.store.data = Object.assign(globalStore.data, opt.data)
        this.setData.call(this, this.store.data)
        globalStore.instances.push(this)
        rewriteUpdate(this)
        attached && attached.call(this)
    }
    Component(opt)
}

總結

  • 組件 - 對 WXML、WXSS 和 JS 的封裝,與業務耦合,可複用,難移植
  • 純組件 - 對 WXML、WXSS 和 JS 的封裝,與業務解耦,可複用,易移植
  • 插件 - 小程序插件是對一組 JS 接口、自定義組件或頁面的封裝,與業務耦合,可複用

Star & Fork 小程序解決方案

https://github.com/dntzhang/westore

License

MIT @dntzhang

相關文章
相關標籤/搜索