vue3的响应式原理(重点)
- 通过Proxy代理:拦截对象中任意属性的变化(属性的读写、增加、删除)
const p = new Proxy(target, handler)
- target:源数据
- handler:一个对象,声明了代理源数据的指定行为,支持的拦截操作如get、set、deleteProperty
- 通过Reflect反射:一个内置对象,对被代理对象(源对象)的属性进行操作;可以通过内置的get、set、deleteProperty方法操作源对象
- 响应式原理实现简易代码如下:
setup () { // 源对象 let person = { name: '张三', age: 20, sex: '男' } new Proxy(person, { // 当源对象person被读取时调用 // getter有两个参数,target代表源对象person,propName为源对象中被读取属性的属性名 get(target, propName) { // 通过Reflect反射对源对象进行操作 return Reflect.get(target, propName) }, // 当源对象被修改或增加属性时调用 // setter有两个参数,target代表源对象person,propName为源对象中被修改或增加属性的属性名,value为被修改或增加属性的属性值 set(target, propName, value) { // 通过Reflect反射对源对象进行操作 Reflect.set(target, propName, value) }, // 当源对象中属性被删除时调用 // deleteProperty有两个参数,target代表源对象person,propName为源对象中被删除属性的属性名 deleteProperty(target, propName) { return Reflect.deleteProperty(target, propName) } }) }
总结ref与reactive区别
- 定义数据角度:
- ref:定义一个响应式的基本类型数据
- reactive:定义一个响应式的对象类型数据
- 注意:ref也可以用于定义对象(数组)类型数据,在内部会自动通过reactive转化为代理对象
- 响应式原理角度
- ref:响应式依然依靠Object.defineProperty()中的set()方法与get()方法实现
- reactive:响应式依靠Proxy代理源对象与Reflect反射操作源对象实现
- 使用角度
- ref:操作数据需要加.value,在html模板中不需要加.value
- reactive:操作数据均不需要加.value