小程序解决方案 Westore - 组件、纯组件、插件开发
数据流转
先上一张图看清 Westore 怎么解决小程序数据难以管理和维护的问题:

非纯组件的话,可以直接省去 triggerEvent 的过程,直接修改 store.data 并且 update,形成缩减版单向数据流。
Github: https://github.com/dntzhang/westore
组件
这里说的组件便是自定义组件,使用原生小程序的开发格式如下:
Component({
properties: { },
data: { },
methods: { }
})
使用 Westore 之后:
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 的痛点:
- 使用 this.data 可以获取内部数据和属性值,但不要直接修改它们,应使用 setData 修改
- setData 编程体验不好,很多场景直接赋值更加直观方便
- setData 卡卡卡慢慢慢,JsCore 和 Webview 数据对象来回传浪费计算资源和内存资源
- 组件间通讯或跨页通讯会把程序搞得乱七八糟,变得极难维护和扩展
没使用 westore 的时候经常可以看到这样的代码:

使用完 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
小程序解决方案 Westore - 组件、纯组件、插件开发的更多相关文章
- 微信小程序开发03-这是一个组件
编写组件 基本结构 接上文:微信小程序开发02-小程序基本介绍 我们今天先来实现这个弹出层: 之前这个组件是一个容器类组件,弹出层可设置载入的html结构,然后再设置各种事件即可,这种组件有一个特点: ...
- 小程序-文章:微信小程序常见的UI框架/组件库总结
ylbtech-小程序-文章:微信小程序常见的UI框架/组件库总结 1.返回顶部 1. 想要开发出一套高质量的小程序,运用框架,组件库是省时省力省心必不可少一部分,随着小程序日渐火爆,各种不同类型的小 ...
- 微信小程序常见的UI框架/组件库总结
想要开发出一套高质量的小程序,运用框架,组件库是省时省力省心必不可少一部分,随着小程序日渐火爆,各种不同类型的小程序也渐渐更新,其中不乏一些优秀好用的框架/组件库. 1:WeUI 小程序–使用教程 h ...
- 微信小程序入门与实战 常用组件API开发技巧项目实战*全
第1章 什么是微信小程序? 第2章 小程序环境搭建与开发工具介绍 第3章 从一个简单的“欢迎“页面开始小程序之旅 第4章 第二个页面:新闻阅读列表 第5章 小程序的模板化与模块化 第6章 构建新闻详情 ...
- Vant Weapp小程序蹲坑之使用card组件显示价格
问题 在基于mpvue+Vant Weapp组件库实战过程中,问题越来越多.网络上所谓的"坑"总结,仅仅不过是其开发中所遭所遇之"坑"而已--估计后面的&quo ...
- 微信小程序学习笔记五 常见组件
1. 常见组件 重点讲解小程序中常用的布局组件 1.1 view 代替 原来的div标签 <!-- pages/index/index.wxml --> <view hover-cl ...
- 微信小程序学习笔记四 自定义组件
1. 自定义组件 类似Vue或react中的自定义组件 小程序允许我们使用自定义组件的方式来构建页面 1.1 创建自定义组件 类似于页面, 一个自定义组件由json wxml wxss js 4个文件 ...
- 微信小程序解决方案合集
微信小程序解决方案合集:http://www.wxapp-union.com/special/solution.html 跳坑系列:http://www.wxapp-union.com/forum.p ...
- 3元购买微信小程序解决方案一个月
一.登录微信公众平台https://mp.weixin.qq.com/ 二.点击立即注册.注意:这里不要用微信公众号登录,小程序账号和微信公众号是不同的. 三.在注册页面点击小程序板块. 四.进入小程 ...
随机推荐
- (网页)table加上分页,优点可随便加样式
1.先有静态的页面: <div class="col-xs-12"> <table id="tbtablesaleinfo" class=&q ...
- mysql之连接查询、联合查询、子查询
本文内容: 连接查询 联合查询 子查询 from子查询 where子查询 exists子查询 首发日期:2018-04-11 连接查询: 连接查询就是将多个表联合起来查询,连接查询方式有内连接.外连接 ...
- Node.js学习记录(一)--安装设置篇
安装Node window window上安装node可选择以下两种方式: 方式一:直接进入官网下载安装 进入node.js官网点击windows,选择.msi后缀的,根据自己的电脑选择对应的64位或 ...
- linux(centos)无中文输入,如何解决
1.终端执行安装命令 yum install "@Chinese Support" 2.如下图,多出Input method 3.点击进行配置 4.reboot重启系统,新建一个文 ...
- 同一个菜品商家中心和erp价格显示不一致解决方案FAQ
1.适用场景: 2.问题原因:子账号在商家中心改了价格 3.解决办法: (1).子账号登录商家后台修改 再同步(2).ERP上商品管理 修改价格
- Visual Studio Team Services Demo Generator简介
Visual Studio Team Services Demo Generator简介 Visual Studio Team Services Demo Generator能够帮助我们在Visual ...
- 自动化测试基础篇--Selenium iframe定位问题
摘自https://www.cnblogs.com/sanzangTst/p/7473437.html 有时候我们在定位的途中发现一个现象,元素就在那儿,不离不去,但是我们怎么整就是定不了位,这个时候 ...
- 简单易懂的程序语言入门小册子(1.5):基于文本替换的解释器,递归定义与lambda演算的一些额外说明
这一篇接在第一篇lambda演算的后面.讲讲一些数学知识. 经常有些看似很容易理解的东西,一旦要描述得准确无误,就会变得极为麻烦. 软件工程里也有类似情况:20%的代码实现了核心功能,剩下80%的代码 ...
- [福大软工] Z班 软件工程实践总结 作业成绩
作业要求 http://www.cnblogs.com/easteast/p/8081265.html 评分细则 本次作业评分满分为20分,分为五个部分,分别如下: 回望过去(5'):以实际数据总结分 ...
- 加一的golang实现
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一. 最高位数字存放在数组的首位, 数组中每个元素只存储一个数字. 你可以假设除了整数 0 之外,这个整数不会以零开头. 输入: [,,] ...