實現一個最小版本vue(二)之observer
阿新 • • 發佈:2020-07-06
Vue
- 功能
- 負責接收初始化的引數
- 負責把data中的屬性注入到vue例項,轉化稱getter,setter
- 負責呼叫observer監聽data中所有屬性的變化
- 負責呼叫compiler解析指令/差值表示式
- 結構
observer
- 功能
- 負責把data選項中的屬性轉換成響應式資料
- data中的某個屬性也是物件,把該屬性轉換成響應式資料
- 資料變化發出通知
- 結構
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>mini vue</title> </head> <body> <div id="app"> <h1>差值表示式</h1> <h3>{{msg}}</h3> <h3>{{count}}</h3> <h1>v-text</h1> <div v-text="msg"></div> <h1>v-model</h1> <input type="text" v-model="msg" /> <input type="text" v-model="count" /> </div> <script src="js/observer.js"></script> <script src="js/vue.js"></script> <script> let vm = new Vue({ el: '#app', data: { msg: 'hello vue', count: 28, }, }) console.log(vm.msg) </script> </body> </html>
// observer.js class Observer { constructor (data) { this.walk(data) } walk (data) { // 1.判斷data是否時物件 if (!data || typeof data !== 'object') { return } // 2.遍歷data物件所有屬性 Object.keys(data).forEach(key => { this.defineReactive(data, key, data[key]) }) } defineReactive (obj, key, val) { Object.defineProperty(obj, key, { enumerable: true, configurable: true, get () { // 如果使用obj[key],會發生堆疊溢位錯誤 // return obj[key] return val }, set (newValue) { if (newValue === val) { return } val = newValue // 傳送通知 }, }) } }
// vue.js class Vue { constructor (options) { // 1.通過屬性儲存選項的資料 this.$options = options || {} this.$data = options.data || {} this.$el = typeof options.el === 'string' ? document.querySelector(options.el) : options.el // 2.把data中的成員轉化稱getter和setter,注入到vue例項 this._proxyData(this.$data) // 3. 呼叫observer物件,監聽資料變化 new Observer(this.$data) // 4.呼叫compiler物件,解析指令和差值表示式 } _proxyData (data) { // 遍歷data中所有屬性 Object.keys(data).forEach(key => { Object.defineProperty(this, key, { enumerable: true, configurable: true, get () { return data[key] }, set (newValue) { if (newValue === data[key]) { return } data[key] = newValue }, }) }) // 把data的屬性注入到vue例項 } }