这是我参与2022首次更文挑战的第22天,活动详情查看:2022首次更文挑战
一、实现数据从data到view的单向数据绑定
- 当data发生变化的时候首先触发数据劫持的setter函数
set(newVal) {
value = newVal
Observe(value)
// 通知每个订阅者更新自己的文本
dep.notify()
}
复制代码
setter函数先改变新的值,然后通知每一个订阅者。
- Dep类的notify函数通知每一个订阅者watcher
notify() {
this.subs.forEach(watcher => watcher.update())
}
复制代码
- Watcher类的update函数获取最新的值并调用渲染函数。
update() {
const value = this.key.split('.').reduce((newObj,k) => newObj[k],this.vm)
this.cb(value);
}
复制代码
- 渲染函数执行渲染
new Watcher(vm,execResult[1],(newValue) => {
node.textContent = text.replace(regMustache,newValue);
})
复制代码
二、实现文本框的单向数据绑定
在渲染函数中首先判断当前节点是否为input并且含有属性v-model,有则获取值并创建watcher实例。
// 判断当前的节点是否为input框
if (node.nodeType === 1 && node.tagName.toUpperCase() === 'INPUT') {
// 得到当前元素的所有属性节点
const attrs = Array.from(node.attributes);
const findResult = attrs.find(x => x.name === 'v-model')
if (findResult) {
// 获取当前v-model属性的值 v-model="name" v-model="info.a"
const expStr = findResult.value;
const value = expStr.split('.').reduce((newObj,k) => newObj[k],vm);
node.value = value;
// 创建Watcher的实例
new Watcher(vm,expStr,(newValue) => {
node.value = newValue;
})
}
}
复制代码
三、实现文本框的双向数据绑定
实现文本框的双向数据绑定重点是在单向数据绑定的基础上,监听文本框的输入事件,拿到文本框的最新值,并将最新值更新到vm上即可。
// 判断当前的节点是否为input框
if (node.nodeType === 1 && node.tagName.toUpperCase() === 'INPUT') {
// 得到当前元素的所有属性节点
const attrs = Array.from(node.attributes);
const findResult = attrs.find(x => x.name === 'v-model')
if (findResult) {
// 获取当前v-model属性的值 v-model="name" v-model="info.a"
const expStr = findResult.value;
const value = expStr.split('.').reduce((newObj,k) => newObj[k],vm);
node.value = value;
// 创建Watcher的实例
new Watcher(vm,expStr,(newValue) => {
node.value = newValue;
})
// 监听文本框的input输入事件,拿到文本框的最新值,并把最新值更新到vm上即可
node.addEventListener('input',e => {
const keyArr = expStr.split('.');
const obj = keyArr.slice(0,keyArr.length-1).reduce((newObj,k) => newObj[k],vm);
obj[keyArr[keyArr.length - 1]] = e.target.value;
})
}
}
复制代码
总结
Vue的双向数据绑定是数据劫持、模板编译、发布订阅模式等综合知识点的体现,是我们必须要学会并掌握的知识点。