手寫Vue3.0 API(B站李南江)
阿新 • • 發佈:2020-12-23
一、Vue3.0響應式
1.在Vue2.x中是通過defineProperty來實現響應式資料的
2.在Vue3.x中是通過Proxy來實現響應式資料的
let obj = { name: 'lng', age: 18 } // 原始物件
let state = new Proxy(obj, { // 攔截原始物件進行操作
get (obj, key) {
console.log(obj, key) // { name: 'lng', age: 18 } "name"
return obj[key]
},
set (obj, key, value) {
obj[key] = value
console.log(obj, key, value) // {name: "jz", age: 18} "name" jz
// return true // 更新UI
}
})
console.log(state.name) // get--lng
state.name = 'jz' // set
二、shallowReactive和shallowRef
function shallowRef(val) { // shallowRef本質還是shallowReactive
return shallowReactive({ value: val })
}
function shallowReactive(obj) {
return new Proxy(obj, {
get(obj, key) {
return obj[key]
},
set(obj, key, value) {
obj[key] = value
console.log('更新UI介面')
return true
}
})
}
let obj = {
a: 'a',
gf: {
b: 'b',
f: {
c: 'c',
s: {
d: 'd'
}
}
}
}
/*
let state = shallowReactive(obj)
// state.a = 1 // 更新UI介面
state.gf.b = 2
state.gf.f.c = 3
state.gf.f.s.d = 4
*/
let state = shallowRef(obj)
// state.value.a = 1
// state.value.gf.b = 2
// state.value.gf.f.c = 3
// state.value.gf.f.s.d = 4
state.value = {
a: '1',
gf: {
b: '2',
f: {
c: '3',
s: {
d: '4'
}
}
}
}
console.info(state.value)
三、reactive和ref
function ref(val) {
return reactive({value: val})
}
function reactive(obj) {
if(typeof obj === 'object') {
if (obj instanceof Array) {
// 如果是一個數據,那麼取出陣列中的每一個元素
// 判斷每一個元素是否又是一個物件,如果又是一個物件,那麼也需要包裝成 Proxy
obj.forEach((item, index) => {
if(typeof item === 'object') {
obj[index] = reactive(item)
}
})
} else {
// 如果是一個物件,那麼去除物件屬性的取值
// 判斷物件屬性的取值是否又是一個物件,如果又是一個物件,那麼也需要包裝成 Proxy
for (let key in obj) {
let item = obj[key]
if (typeof item === 'object') {
obj[key] = reactive(item)
}
}
}
} else {
console.warn(`${JSON.stringify(obj)} is not object`)
}
return new Proxy(obj, {
get(obj, key) {
return obj[key]
},
set(obj, key, value) {
obj[key] = value
console.log('更新UI介面')
return true
}
})
}
let obj = {
a: 'a',
gf: {
b: 'b',
f: {
c: 'c',
s: {
d: 'd'
}
}
}
}
// let state = reactive(obj)
// state.a = 1 // 更新UI介面
// state.gf.b = 2 // 更新UI介面
// state.gf.f.c = 3 // 更新UI介面
// state.gf.f.s.d = 4 // 更新UI介面
let arr = [{id: 1, name: '魯班'}, {id: 2, name: '虞姬'}]
let state = reactive(arr)
state[0].name = '張三' // 更新UI介面
state[0].age = 666 // 更新UI介面
state[1].id = 3 // 更新UI介面
四、readonly和shallowReadonly
function readonly(obj) { // readonly遞迴只讀
if(typeof obj === 'object') {
if (obj instanceof Array) {
// 如果是一個數據,那麼取出陣列中的每一個元素
// 判斷每一個元素是否又是一個物件,如果又是一個物件,那麼也需要包裝成 Proxy
obj.forEach((item, index) => {
if(typeof item === 'object') {
obj[index] = readonly(item)
}
})
} else {
// 如果是一個物件,那麼去除物件屬性的取值
// 判斷物件屬性的取值是否又是一個物件,如果又是一個物件,那麼也需要包裝成 Proxy
for (let key in obj) {
let item = obj[key]
if (typeof item === 'object') {
obj[key] = readonly(item)
}
}
}
} else {
console.warn(`${JSON.stringify(obj)} is not object`)
}
return new Proxy(obj, {
get(obj, key) {
return obj[key]
},
set(obj, key, value) {
console.warn(`${key}是隻讀的,不能賦值`)
return true
}
})
}
function shallowReadonly(obj) { // shallowReadonly只讀,但不是遞迴只讀
return new Proxy(obj, {
get(obj, key) {
return obj[key]
},
set(obj, key, value) {
console.warn(`${key}是隻讀的,不能賦值`)
}
})
}
let obj = {
a: 'a',
gf: {
b: 'b',
f: {
c: 'c',
s: {
d: 'd'
}
}
}
}
// let state = shallowReadonly(obj)
// state.a = 1 // a是隻讀的,不能賦值
// state.gf.b = 2 // 空行
let state1 = readonly(obj)
state1.a = 1 // a是隻讀的,不能賦值
state1.gf.b = 2 // b是隻讀的,不能賦值