目標(biāo)
指定一個Vue實(shí)例,可以渲染出對應(yīng)的HTML,并且當(dāng)數(shù)據(jù)變動時重新渲染。
例如:
let app = new Vue({
el: '#app',
data: {
user: {
name: 'youngwind',
age: 25,
location: {
province: 'GD',
city: 'GZ'
},
school: 'bupt',
major: 'computer'
}
}
})
<div id="app">
<p>姓名:{{user.name}}</p>
<p>年齡:{{user.age}}</p>
<div>
<p>省份:{{user.location.province}}</p>
<p>城市:{{user.location.city}}</p>
</div>
</div>
結(jié)果如下:

結(jié)果
思路
- 根據(jù)
el屬性找到對應(yīng)的根元素 - 記錄原HTML。
- 使用正則表達(dá)式找到需要替換的部分,然后根據(jù)
data屬性對{{}}內(nèi)的字符串進(jìn)行求值。把修改后的HTML賦值回去。 - 監(jiān)視數(shù)據(jù)的變動,如果數(shù)據(jù)有改變,就重復(fù)上一步。
其中前幾步實(shí)現(xiàn)都不難,最主要的部分就是第四步。
這里需要實(shí)現(xiàn)一個Observer類,它接受一個對象作為監(jiān)視的值。然后當(dāng)對象產(chǎn)生變化時,需要發(fā)出消息。
怎么發(fā)出消息?
- 實(shí)現(xiàn)一個
EventHandler類,有一個屬性$listeners,2個函數(shù)$on和$emit,前者對于某個事件把指定的函數(shù)存入對應(yīng)的監(jiān)聽器中,后者對于某個事件調(diào)用其對應(yīng)的所有監(jiān)聽器。(發(fā)布-訂閱模式)
怎么監(jiān)視屬性的修改?
- 遍歷對象的每個屬性,使用
Object.defineProperty設(shè)置屬性的getter,如果值改變了就調(diào)用$emit方法。
如果對象內(nèi)還嵌套對象怎么辦?
- 使用遞歸的方法,遍歷每個對象的每個屬性(實(shí)際做的時候沒考慮繼承的),如果屬性是一個對象則繼續(xù)
new Observer。
如果屬性修改后的值是對象怎么辦?
- 檢測屬性修改后的類型,如果是對象則也要
new Observer。
內(nèi)層屬性的修改如何傳遞到上層?
- 例如
user.location是一個對象,為location的每個屬性$on一個函數(shù),內(nèi)容是在user里$emit location,這樣就實(shí)現(xiàn)了層層上傳。
樣例地址
https://github.com/huhk-sysu/ife-study/blob/master/vue/hw5/hw5.js