代碼參考/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>
複製代碼