手写MVVM框架-模板渲染2
上一章我们处理了在页面初始化的时候渲染模板,但是如果是在页面上修改了data里面的数据的话是不会修改的,这一章我们来实现这个功能。
添加renderData方法
我们在proxyObject处可以监控到用户改变数据,这个时候触发renderData方法
/**
* data中数据发生变化立即重新渲染
* @param {MiniVue} vm
* @param {string} data
*/
export function renderData(vm, data) {
// 获取当前data关联的vnode数据
const nodes = templateToNode.get(data)
nodes && nodes.forEach((node)=> {
renderNode(vm, node)
})
}
我们在数据劫持的时候调用该方法
/**
* 代理Object数据
* @param {*} vm
* @param {*} data
*/
function proxyObject(vm, data, namespace) {
// 创建代理对象
let proxyObj = {}
for(let key in data) {
Object.defineProperty(proxyObj, key, {
configurable: true, // 可配置
get() {
return data[key]
},
set(newValue) {
data[key] = newValue
renderData(vm, getNameSpace(namespace, key))
}
})
// 为MiniVue的根实例添加属性
Object.defineProperty(vm, key, {
configurable: true, // 可配置
get() {
return data[key]
},
set(newValue) {
data[key] = newValue
renderData(vm, getNameSpace(namespace, key))
}
})
if(typeof data[key] === 'object') {
proxyObj[key] = constructProxy(vm, data[key], getNameSpace(namespace, key))
}
}
return proxyObj
}
renderData 方法传递的第二个参数就是用户在模板中写的字符串, 这是我们就需要写一个方法getNameSpace来获取这个字符串
// src/core/proxy.js
function getNameSpace(nowNameSpace, nowProp) {
if (nowNameSpace == null || nowNameSpace == "") {
return nowProp;
} else if (nowProp == null || nowProp == "") {
return nowNameSpace;
} else {
return nowNameSpace + "." + nowProp;
}
}
为了验证一些嵌套类型的数据修改,我们在入口文件index.js 中新增一个object类型的数据,并在index.html 中使用
OK 咱们现在在浏览器上修改data中的数据看效果(可以看到已经发生了改变)