代码参考/lesson09/01. watch监听对象属性.htmlhtml
在06课中,实现了对数据的监听,固然Proxy对象同时也能够监听对象类型的数据,咱们须要作的只是将相应的变化渲染到页面中。git
首先,咱们先将_data中的值修改成github
// 用_data保存数据
let _data = {
userInfo: {
name: 'lee',
age: 18
}
}
复制代码
HTML修改成:bash
<div id="app">
姓名:{{userInfo.name}}<br/>
年龄:{{userInfo.age}}
</div>
复制代码
所以须要将render方法中查找模板中要写入值的正则从app
/\{\{\w+\}\}/g
复制代码
替换为:less
/\{\{[\w\.]+\}\}/g
复制代码
这样就能够匹配到HTML模板中的{{userInfo.name}},但咱们从对象中获取数据必须使用data["userInfo"]["name"],而不能直接用data[userInfo.name],所以接下来须要拼接出相应的格式查找到数据,就能够将数据渲染到页面中。ui
完整代码以下:spa
// 将模板中{{}}内部的内容,用数据替换
el.innerHTML = template.replace(/\{\{[\w\.]+\}\}/g, str => {
str = str.substring(2, str.length - 2);
// 将userInfo.name拼接为["userInfo"]["name"],以便查找对象中的属性。
return eval('_data["' + str.split('.').join('"]["') + '"]')
})
复制代码
这样一来咱们就实现了将对象中的属性数据渲染到页面中。 固然同理,咱们就能够实现对象中属性的双向绑定,完整代码以下:双向绑定
JavaScript:code
const el = document.querySelector('#app')
// 获取标签内容做为页面模板
let template = el.innerHTML
// 用_data保存数据
let _data = {
userInfo: {
name: 'lee',
age: 18
}
}
// 为_data设置拦截,经过修改data中属性的值,来修改
let data = new Proxy(_data, {
// 当数据修改时,会被set方法拦截,从而得知数据被修改的值value,以后能够将value渲染到页面中,obj为_data
set(obj, key, value) {
console.log(`设置${key}属性为${value}`)
eval('_data["' + key.split('.').join('"]["') + '"] = value')
// 将数据渲染到页面中
render()
}
})
// 初始化时渲染页面
render()
function render() {
// 将模板中{{}}内部的内容,用数据替换
el.innerHTML = template.replace(/\{\{[\w\.]+\}\}/g, str => {
str = str.substring(2, str.length - 2);
// 将userInfo.name拼接为["userInfo"]["name"],以便查找对象中的属性。
return eval('_data["' + str.split('.').join('"]["') + '"]')
})
// 但检测到数据改变时,将input的值同步
Array.from(document.getElementsByTagName('input'))
// 查找含有v-model属性,即设置了双向绑定的input
.filter((ele) => ele.getAttribute('v-model'))
.forEach((input, index) => {
const name = input.getAttribute('v-model')
eval('input.value = data["' + name.split('.').join('"]["') + '"]')
// 输入框的值变化时,将data中相应属性的值改变
input.oninput = function () {
data[name] = input.value
eval('data["' + name.split('.').join('"]["') + '"] = input.value')
}
})
}
复制代码
HTML:
<div id="app">
<input type="text" v-model="userInfo.name"><br />
姓名:{{userInfo.name}}<br/>
年龄:{{userInfo.age}}
</div>
复制代码