<template><div><h2>{{person.name}}</h2><h2 v-show='person.age'>{{person.age}}</h2><h2>{{person.sex}}</h2><h2>{{person.address}}</h2><button @click='changeName'>修改姓名</button><button @click='changeAge'>修改年龄</button><button @click='addAdress'>添加地址</button><button @click='deleteAge'>删除年龄</button><hr><ul><li v-for="(item, index) in hobby" :key="index">{{ item }}</li></ul><button @click='addHobby'>添加hobby</button><button @click='updateHobby'>修改hobby</button></div></template><script>import { reactive} from'vue'export default {setup() {const person = reactive({name:'张三',age:20,sex:'女'})function changeName(){person.name += '!'}function changeAge(){person.age ++}function addAdress(){person.address = '陕西省'}function deleteAge(){delete person.age}const hobby = reactive(['画画','游泳'])function addHobby(){hobby.push('唱歌')}function updateHobby(){hobby[0] = '烫头'}return { person, changeName,changeAge, addAdress, deleteAge, hobby, addHobby, updateHobby }},}</script>
原理:
<script>const person = {name: '张三',age: 20}const p = new Proxy(person, {get(target, propName) {console.log('有人读取了属性')console.log(target, propName)return target, propName},//新增属性或者修改属性时调用set(target, propName, value) {console.log('有人修改了值')target[propName] = value},deleteProperty(target, propName){console.log('有人删除了属性')return delete target[propName]}})</script>
//真正的vue3实现响应式<script>const person = {name: '张三',age: 20}const p = new Proxy(person, {get(target, propName) {console.log('有人读取了属性')console.log(target, propName)// return target, propNamereturn Reflect.get(target, propName)},//新增属性或者修改属性时调用set(target, propName, value) {console.log('有人修改了值')// target[propName] = valueReflect.set(target, propName, value)},deleteProperty(target, propName){console.log('有人删除了属性')// return delete target[propName]return Reflect.defineProperty(target, propName)}})</script>
总结:
- 实现原理
- 通过 Proxy(代理): 拦截对象中任意属性的变化, 包括:属性值的读写、属性的添加、属性的删除等。
- 通过Reflect(反射): 对源对象的属性进行操作。
- MDN文档中描述的Proxy与Reflect:
关于代理与反射,可以看这篇博文
模拟Vue3中实现响应式
