vue2.x的响应式(数据劫持是响应式根基)
实现原理:
对象类型:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)。
数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。
存在问题:
新增属性、删除属性, 界面不会更新。
直接通过下标修改数组, 界面不会自动更新。
使用:this.$set(属性名,属性值)$delete解决 新增属性、删除属性
使用数组上存在的方法:push,pop。。。
<h2 v-show="person.name">姓名:{{person.name}}</h2>
<h3 v-show="person.sex">性别:{{person.sex}}</h3>
<button @click="addSex">添加sex属性</button>
<button @click="deleteName">删除name属性</button>
import {reactive} from 'vue'
export default {
name: 'App',
setup(){
//数据
let person = reactive({
name:'张三',
age:18,
job:{
type:'前端工程师',
salary:'30K',
a:{
b:{
c:666
}
}
},
hobby:['抽烟','喝酒','烫头']
})
//方法
function changeInfo(){
console.log(person)
person.name = '李四'
person.age = 48
person.job.type = 'UI设计师'
person.job.salary = '60K'
person.job.a.b.c = 999
person.hobby[0] = '学习' //下标
}
function addSex(){
person.sex="男"
}
function deleteName(){
delete person.name
}
//返回一个对象(常用)
return {
person,
changeInfo,
addSex,
deleteName
}
}
}
![](https://img-blog.csdnimg.cn/img_convert/2cf1f4dd760014b31a95d0f09439ec65.png)
vue2.x的响应式 --get set Object.defineProperty
let person = {
name:'张三',
age:18
}
//模拟Vue2中实现响应式
let p = {}
Object.defineProperty(p,'name',{
configurable:true,//可以删除
get(){ //有人读取name时调用
return person.name
},
set(value){ //有人修改name时调用
console.log('有人修改了name属性,我发现了,我要去更新界面!')
person.name = value
}
})
Object.defineProperty(p,'age',{
get(){ //有人读取age时调用
return person.age
},
set(value){ //有人修改age时调用
console.log('有人修改了age属性,我发现了,我要去更新界面!')
person.age = value
}
})
![](https://img-blog.csdnimg.cn/img_convert/6531891546eca64b48fb3d978220bf2d.png)
Vue3.0的响应式--Proxy:代理
实现原理:
通过Proxy(代理): 拦截对象中任意属性的变化, 包括:属性值的读写、属性的添加、属性的删除等。
通过Reflect(反射): 对源对象的属性进行操作。
p代理哪个对象-对数控增删改
//源数据
let person = {
name:'张三',
age:18
}
//person代理对象
const p = new Proxy(person,{
//有人读取p的某个属性时调用
get(target,propName){
console.log(`有人读取了p身上的${propName}属性`)
return target[propName]
},
//有人修改p的某个属性、或给p追加某个属性时调用
set(target,propName,value){
console.log(`有人修改了p身上的${propName}属性,我要去更新界面了!`)
target[propName]=value
},
//有人删除p的某个属性时调用
deleteProperty(target,propName){
console.log(`有人删除了p身上的${propName}属性,我要去更新界面了!`)
return delete target[propName]
}
})
![](https://img-blog.csdnimg.cn/img_convert/dad80be6de0680981cf88ce9763ff9f5.png)
对属性增删改查:Handler
具体的数据:Target
![](https://img-blog.csdnimg.cn/img_convert/931805b4be4367b600250b601125bf34.png)
实际上vue3不是直接的操作,而是Reflect——————反射
读:Reflect.get(obj,"a")
写改: Reflect.set(obj,"b",90)
删:Reflect.deleteProperty(obj,"a")
Reflect.defineProperty 可以set get--有返回值 替换Object.defineProperty 可以使用if判断
![](https://img-blog.csdnimg.cn/img_convert/89d953968bfab594881d1ff1fb058bc6.png)
const p = new Proxy(person,{
//有人读取p的某个属性时调用
get(target,propName){
console.log(`有人读取了p身上的${propName}属性`)
return Reflect.get(target,propName)
},
//有人修改p的某个属性、或给p追加某个属性时调用
set(target,propName,value){
console.log(`有人修改了p身上的${propName}属性,我要去更新界面了!`)
Reflect.set(target,propName,value)
},
//有人删除p的某个属性时调用
deleteProperty(target,propName){
console.log(`有人删除了p身上的${propName}属性,我要去更新界面了!`)
return Reflect.deleteProperty(target,propName)
}
})