简介
对小程序原生框架进行扩展,提供新的特性以及一些通用功能。
使用方法:
import { wrap } from 'mpwjs'
const wApp = wrap(App)
const wComponent = wrap(Component)
const wView = wrap(Component)
wApp.mixin({ ... })
wComponent.mixin({ ... })
wView.mixin({ ... })
wApp()
- 使用 wComponent/wView 创建组件或者页面:
wView({
name: 'User',
props: {
id: {
type: String,
},
},
data: {
name: '',
age: '',
},
})
ps: 上述 Demo 没有使用wView = wrap(Page)是因为 Page 早期(<2.9.2)无法使用Behavior,而且在组件化编程体验上面跟Component不一致,所以统一使用Component。
自定义选项
在支持原生对象所有配置的基础上,增加了自定义选项:
name: string | 组件名称 | 利于调试 |
props: object | 组件属性定义 | 用法跟 Vue 的 props 一致,可以代替原properties |
mixins: Array<options> | 混入 | 支持嵌套,如minxins: [{ mixins: [...]}] |
store: Store | 全局状态对象 | 详情见全局状态管理 |
use: {[local:string]:string} | 引入 store 状态 | |
computed:{[key:string]:(data) => any} | 计算属性 | 文档 |
watch: {[objPath:string]:(...vals) => void} | 数据观测 | 文档 |
cache: string[] | object[] | 路由级数据缓存 | 利用Storage实现 |
globalCache: string[] | object[] | 全局数据缓存 | 利用Storage实现 |
mixins 说明
支持小程序原生 options 以及自定义 options,如果使用如下 mixins:
const B = {
mixins: [D],
}
const C = {
mixins: [E],
}
{
mixins: [B, C],
}
那么混入顺序为:D->B->E->C->A
use 说明
use 声明是为了将 store 状态引入到本地。基本格式为:
{
use: {
localName: 'storeName'
}
}
比如use: { myUser: "user" },那么本地就可以使用this.data.myUser访问 store 中的 user。
局部引用
storeName 支持 object-path,从而可以实现局部 store 状态引入:
{
use: {
avatar: 'user.avatar'
}
}
通配符
引用 store 状态时,请牢记一个规则:父级状态发生改变时,会通知子级;但是子级状态发生改变时,不会通知父级。
比如在页面上引用用户信息use: { user: "user" },那么当$store.setData({ user: newUser})时,页面上引用的 user 会响应式更新。如果是$store.setData({{ "user.avatar": "xx.png" })(只修改用户头像),页面上的 user 不会更新。
如果我们想引用多个 user 的子状态,但是又不想挨个去声明,那么我们可以使用通配符user: { user: "user.**" }。user.**表示我们既引用 user 状态,同时也监听其下所有子状态的更改。
cache 配置说明
{
cache: {
[key: string]: {
value?: any,
expire?: number,
user?: boolean,
query?: boolean,
}
}
}
或者简单罗列 key:
{
cache: Array<string>
}
globalCache 配置与 cache 一致。两者不同地方在于缓存命名空间不同,globalCache 存放于data:xxx,而 cache 存放于data:path/to/some/page/xxx。
cache 配置后,即可作为普通 data 数据来使用,框架本身会负责及时更新 Storage。另外如果 globalCache 与 cache 中有重名配置,优先使用 cache。
全局状态管理
全局状态管理是一个常见需求,因此 mpwjs 提供了一套简单易行的方案。
创建 Store
import { createStore } from 'mpwjs'
const store = createStore({
data: {
user: {
avatar: '',
access: {},
},
},
})
wView.mixin({
store,
})
修改 Store
store 提供了 setData 方法(类似原生 setData 方法,支持 object-path)。比如:
store.setData({
'user.avatar': 'xx.png',
})
组件内部可以使用$store.setData。比如:
wView({
use: {
user: 'user',
},
methods: {
onClick() {
this.$store.setData({
'user.avatar': 'xx.png',
})
},
},
})
切记只有通过 store.setData 才是全局有效的。
监听 Store
支持通过store.watch监听状态改变(类似小程序的 observer),比如:
this.$store.watch('user.**', (user) => {
})
不过 $store.watch 是一个偏底层的 api,一般只在框架层面使用。平时书写 View 页面时,直接使用 watch 选项即可:
wView({
use: {
user: 'user',
},
watch: {
user: function () {
},
},
})
自定义生命周期
beforeLaunch | 在 appLaunch 之前发生 | 以异步队列运行,且会拦截 launch 事件 |
beforeEnter | 在组件 attach 之前发生 | 以异步队列运行,且会拦截 attached、load、show 事件 |
beforeShow | 在组件 show 之前发生 | 以异步队列运行,且会拦截 show 事件 |
页面间通信
微信小程序通过getCurrentPages()可以获取到当前的页面栈,如果这些页面之间希望通信的话,则可以使用全局混入的$tab 对象,比如:
this.$tab.addMessageListener(({ message, origin }) => {
console.log(message, origin)
})
this.$tab.postMessage({ type: 'loaded', data: 'hello world!' }, 'home')
this.$tab.postMessage({ type: 'loaded', data: 'hello world!' }, '*')
this.$tab.postMessage({ type: 'loaded', data: 'hello world!' }, /\/detail$/)
this.$tab.postMessage(
{ type: 'load', data: 'hello world!' },
'*',
(err, res) => {
console.log(res)
}
)
this.$tab.addMessageListener(({ message, origin, answer }) => {
setTimeout(() => answer(null, 'nice to meet you!'), 500)
})