手写Vue3.0 API(B站李南江)
一、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是只读的,不能赋值