响应式原理解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| function observe(data, cb){ Object.keys(data).forEach((key) => { let val = data[key] Object.defineProperty(data,key,{ enumerable:true, configurable:true, get: () => { console.log("read") return val }, set: (newVal) =>{ val = newVal cb() } }) }) } class Vue { constructor(options){ this._data = options.data observe(this._data, options.cb) } } let app = new Vue({ el:"#app", data:{ text:"text", text2:"text2" }, cb: function(){ console.log('change') } })
console.log(app._data.text) app._data.text = '1' console.log(app._data.text)
|
为了让读取跟修改更加方便,我们采用代理的形式对代码进行如下修改:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| function observe(value, cb) { const that = this Object.keys(value).forEach((key) => Object.defineProperty(that, key, { enumerable: true, configurable: true, get: ()=>{ console.log('read') return value[key] }, set:newVal=> { value[key] = newVal; cb(); } }) ) }
class Vue { constructor(options) { observe.call(this, options.data,options.render) } }
let app = new Vue({ el: '#app', data: { text: 'text', text2: 'text2' }, render: function(){ console.log("change"); } }) console.log(app.text) app.text = 1 console.log(app.text)
|
这样一来我们就可以用app.text代替app._data.text了。