vue2
基于Object.defineProperty()實(shí)現(xiàn)
Object.defineProperty() 在一個(gè)對(duì)象上定義一個(gè)新的屬性心铃,或者修改這個(gè)對(duì)象上已經(jīng)存在的屬性
Object.defineProperty(obj, prop, desc)
- obj: 目標(biāo)對(duì)象
- prop: 對(duì)象的key
- desc: 屬性描述
desc 參數(shù)為一個(gè)對(duì)象,里面的屬性是
let Person = {}
let backup = null
Object.defineProperty(Person, 'name', {
value: 'Jack', // key 的值
writable: true, // 是否可寫(xiě)胞枕,默認(rèn)false
enumerable: true, // 是否可枚舉柴梆,是否可for in
configurable: ture, // 是否可配置人弓,是否可刪除等癞季,默認(rèn)fasle
get: function() { // 獲取數(shù)據(jù)方法
return backup
},
set: function(newVal) { // 更改方法,接受參數(shù)為新值
backup = newVal
}
})
基于Object.defineProperty(obj, prop, desc)的vue雙向數(shù)據(jù)綁定
function vue() {
this.$data = {
testData: 1
}
this.el = docunment.getElementById('app')
this.virtualDom = ''
this.observer(this.$data)
this.render()
}
vue.prototype.observer = function(data) {
let self = this;
let backup = null;
for(let key in data) {
backup = data[key] // 先備份數(shù)據(jù)
if (typeof backup === 'object') {
this.observer(backup)
} else {
Object.defineProperty(data, key, {
get: function() {
// 依賴收集
return backup // 一定要return出去才可以
},
set: function(newVal) {
backup = newVal
self.render() // 刷新視圖
}
})
}
}
}
vue.prototype.render = functin() {
this.virtualDom = 'a test vue' + this.$data.testData
this.el.innerHtml = this.virtualDom
}
vue3 基于Proxy
與Object.defineProperty(obj, prop, desc)方式相比有以下優(yōu)勢(shì):
- 丟掉麻煩的備份數(shù)據(jù)
- 省去for in 循環(huán)
- 可以監(jiān)聽(tīng)數(shù)組變化
- 代碼更簡(jiǎn)化
function vue() {
this.$data = {
testData: 1
}
this.el = docunment.getElementById('app')
this.virtualDom = ''
this.observer(this.$data)
this.render()
}
vue.prototype.observer = function(data) {
let self = this;
this.$data = new Proxy(this.data, {
get: function(target, key, vceiver) {
return target[key]
},
set: function(target, key, value, vceiver) {
target[key] = value
slef.render()
}
})
}
vue.prototype.render = functin() {
this.virtualDom = 'a test vue' + this.$data.testData
this.el.innerHtml = this.virtualDom
}