目录
logic层主要运行我们的业务逻辑代码,我们写的大部分业务代码比如 methods 和 生命周期里面的代码都在这里,通过接收来自 UI层的生命周期触发通知或者事件调用通知来执行相应函数。
初始化实例
当收到 UI层vue实例的created通知,则在logic层也对应实现一份相对简单的实例数据
const componentOptions = compCtx(pagePath).default
const c = (componentMap[`${pid},${cid}`] = new Component(componentOptions, {
route: res.route,
cid,
pid,
initData: res.initData
}))
其中 cid
是组件id,使用 vue实例的唯一id;而 pid
是页面id,由路由创建页面的时候分配。
我们看看 Component
做了什么:
class Component {
constructor(options, { cid, pid, route, initData }) {
this.cid = cid
this.pid = pid
this._route = route
this.data = initData // 含props
// 处理方法事件
if (isObject(options.methods)) {
for (const k in options.methods) {
if (isFunction(options.methods[k])) {
this[k] = options.methods[k]
}
}
}
// 处理生命周期
for (const k in lifetimeMappings) {
// 先设置默认的生命周期
this[lifetimeMappings[k]] = noop
}
for (const k in lifetimeMappings) {
if (isFunction(options[k])) {
this[lifetimeMappings[k]] = options[k]
}
}
if (cid === 1) {
// page组件
this.onShow = isFunction(options.onShow) ? options.onShow : noop
this.onHide = isFunction(options.onHide) ? options.onHide : noop
} else {
// 子组件
this.onShow = noop
this.onHide = noop
if (isObject(options.pageLifetimes)) {
if (isFunction(options.pageLifetimes.show)) {
this.onShow = options.pageLifetimes.show
}
if (isFunction(options.pageLifetimes.hide)) {
this.onHide = options.pageLifetimes.hide
}
}
}
}
...
}
- 为了不需要同步去实现
props
和computed
逻辑,初始数据 initData 不使用业务 options 写的,而是同步UI层的数据(包括data, props, computed) - methods和生命周期同步自 options。
以下是一个生成的实例:
image.png
setData
由于Vue的响应式原理是一个比较复杂的工程,逻辑层用了跟小程序类似的 setData
来手动触发变化。
每一次setData先对自身实例数据进行修改,再通知到UI层。
class Component {
...
setData(data) {
const newData = {}
for (const k in data) {
try {
mergeData(this.data, k, data[k])
newData[k] = data[k]
} catch (e) {
console.error(e.message)
}
}
postMessageToPage(
{
cmd: SET_DATA,
data: newData
},
this.cid,
this.pid
)
}
}
以上代码中,我们发现了 mergeData
这函数,因为小程序的setData是支持 a.b.c.d
这种key值方式,这样可以避免大量数据的修改。
function mergeData(parent, key, value) {
if (isString(key)) {
if (key.indexOf('.') !== -1) {
let [a, ...b] = key.split('.')
mergeData(parent[a], b.join('.'), value)
return
}
}
parent[key] = value
}