響應式
- 是一種面向數據流和變化傳播的編程範式。這意味着能夠在編程語言中很方便地表達靜態或動態的數據流,而相關的計算模型會自動將變化的值經過數據流進行傳播。
- Vue 2+ 版本基於Object.defineProperty實現數據雙向綁定,即數據變化時,視圖也變化。
- Object.defineProperty用法:
let obj = {}
Object.defineProperty(obj, 'value', {
get () {
return 1
},
set (newValue) {
console.log('set')
value = newValue
}
})
// 控制檯
// obj.value => 1
// obj.value = 2 => set
// 將x轉換成能夠監聽變化的對象
let x = ref(1)
let ref = initValue => {
let value = initValue
return Object.defineProperty({}, 'value', {
get () {
return value
},
set (newValue) {
value = newValue
active() // x變化時觸發y變化
}
})
}
// 當x變化時,y相應改變(f函數模擬變化)
let f = n => n * 100 + 100
let active
let onXChange = (cb) => {
active = cb
active() // 開始時觸發一次
}
onXChange(() => {
y = f(x.value)
console.log(y)
})
x.value = 2 // 300
- 因爲一個變量的修改會涉及到模板中多處的變化,須要將依賴變量的地方收集起來,等更新時批量操做
class Dep {
constructor() {
// Set 數據結構 相似於數組,但成員都是惟一的
// 經過new生成Set數據結構
this.deps = new Set()
}
depend () {
// 依賴收集
if (active) {
// 經過add()方法向Set結構加入成員
this.deps.add(active)
}
}
notify () {
// 觸發
this.deps.forEach(dep => dep())
}
}
- 改造一下onXChange函數,避免重複收集
- 在get中收集依賴,在set中觸發
- 最終實現:
// 假如x變化,y和z都要變化
let x
let y
let z
let fy = n => n * 100 + 100
let fz = n => n + 1
let active
let onXChange = (cb) => {
active = cb
active()
active = null // 避免重複收集
}
// 當X變化時,引發y和z的變化,一個變化引起多個變化
class Dep {
constructor() {
// Set 數據結構 相似於數組,但成員都是惟一的
// 經過new生成Set數據結構
this.deps = new Set()
}
depend () {
// 依賴收集
if (active) {
// 經過add()方法向Set結構加入成員
this.deps.add(active)
}
}
notify () {
// 觸發
this.deps.forEach(dep => dep())
}
}
let ref = initValue => {
let value = initValue
let dep = new Dep()
return Object.defineProperty({}, 'value', {
get () {
dep.depend()
return value
},
set (newValue) {
value = newValue
dep.notify()
}
})
}
x = ref(1)
onXChange(() => {
y = fy(x.value)
console.log(y)
})
onXChange(() => {
z = fz(x.value)
console.log(z)
})
x.value = 2
/*
控制檯打印
200
2
300
3
*/