响应式数据
让元素在 Vue / React 等前端框架 中支持响应式数据。
修改元素数据 或 响应式数据,都能得到同步更新。
关键属性
proxyData: IUIInputData
getter 响应式数据,用于代理元素数据。
TIP
注意:访问 proxyData 后会自动创建响应式数据对象 __proxyData,注意合理使用,会增加内存开销。
数据层级
目前只支持第一层属性的响应式,如果数据为对象、数组类型的,需要更新为新对象才能生效。
ts
proxyData.fill.rotation = 30 // 无效
proxyData.fill = proxyData.fill // 无效
proxyData.fill = { ...proxyData.fill, rotation: 30 } // 有效, 已更新为一个新对象
内部需实现的方法
已提供 Vue3 的 示例 (proxyData.ts),后续会有主流框架的相关插件。
createProxyData ( ): IUIInputData
根据不同的前端框架创建响应式数据 __proxyData(内部使用)。
setProxyAttr ( name: string
, newValue: IValue
)
设置元素属性时,同步设置代理数据(内部使用)。
getProxyAttr ( name: string
): IValue
获取元素属性时,优先返回代理数据(内部使用)。
示例
Vue3 中实现响应式数据
可以看到页面中的数据自动从 100 变为 1,再变为 2,点击数字之后变为 3。
vue
<script setup lang="ts">
import { Rect } from 'leafer-ui'
import './proxyData' // 重写 proxyData,全局只需引入一次
const rect = new Rect()
const proxyData = rect.proxyData // 获取 rect 的响应式代理数据
setTimeout(() => {
proxyData.width = 1 // 修改响应式代理数据, 同步更新页面
}, 1000)
setTimeout(() => {
rect.width = 2 // 修改rect数据, 同步更新页面
}, 2000)
</script>
<template>
<div class="rect" @click="rect.width = 3">{{ proxyData.width }}</div>
</template>
<style scoped>
.rect {
font-size: 200px;
cursor: pointer;
}
</style>
ts
import { shallowReactive, watch } from 'vue'
import { UI, defineKey } from 'leafer-ui'
// 定义proxyData
defineKey(UI.prototype, 'proxyData', {
get() {
return this.__proxyData
? this.__proxyData
: (this.__proxyData = this.createProxyData())
},
})
// 设置元素属性时,内部同步设置代理数据
UI.prototype.setProxyAttr = function (name: string, newValue: unknown): void {
const data = this.__proxyData as any
if (data[name] !== newValue) data[name] = newValue
}
// 获取元素属性时,内部优先返回代理数据
UI.prototype.getProxyAttr = function (name: string): any {
const value = (this.__proxyData as any)[name]
return value === undefined ? this.__.__get(name) : value
}
// 创建响应式数据
UI.prototype.createProxyData = function () {
// 1.获取所有样式数据(含默认值)
const data = this.__.__getData()
// 2. 生成响应式数据
const proxyData = shallowReactive(data)
// 3.观察响应式数据变化,同步更新元素数据
for (const name in data) {
watch(
() => proxyData[name], // source
(newValue) => {
if (this.__.__get(name) !== newValue) (this as any)[name] = newValue
} // callback
)
}
return proxyData
}