小程序解决方案 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

相关文章
相关标签/搜索