第一部分:观察下面的运行图片
第二部分 先给出结论。
实现原理:
对象类型:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)。
数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。
Object.defineProperty(data, 'count', { get () {}, set () {} })
存在问题:
新增属性、删除属性, 界面不会更新。
直接通过下标修改数组, 界面不会自动更新。
Vue3.0的响应式:
实现原理:
通过Proxy(代理): 拦截对象中任意属性的变化, 包括:属性值的读写、属性的添加、属性的删除等。
通过Reflect(反射): 对源对象的属性进行操作。
MDN文档中描述的Proxy与Reflect:
Proxy:Proxy - JavaScript | MDN
Reflect:Reflect - JavaScript | MDN
new Proxy(data, { // 拦截读取属性值 get (target, prop) { return Reflect.get(target, prop) }, // 拦截设置属性值或添加新属性 set (target, prop, value) { return Reflect.set(target, prop, value) }, // 拦截删除属性 deleteProperty (target, prop) { return Reflect.deleteProperty(target, prop) } }) proxy.name = 'tom'
第三步部分 谈一下 Vue2.0的原理到Vue3.0原理的过程:
在这里采用了ES6语法的新的特性
let people = { names: "我是Vue2的数据内容", age: 23, height: 190, weight: 45, }
// 模拟Vue2响应式原理 let po = {} Object.defineProperty(po,'names',{ get() { // 有人读取name时候调用数据 return people.names }, set(Value) { // 有人修改name时调用的数据 console.log('有人修改name时调用的数据,我发现了数据,我要去更新页面了') people.names = Value } }) Object.defineProperty(po, 'age', { get() { // 有人读取name时候调用数据 return people.age }, set(Value) { // 有人修改name时调用的数据 console.log('有人修改age时调用的数据,我发现了数据,我要去更新页面了') people.age = Value } })
这张图解释了上面的代码情况内容
在Vue2中发现的问题==>在Vue3中得到了解决
存在问题:
- 新增属性、删除属性, 界面不会更新。
- 直接通过下标修改数组, 界面不会自动更新。
第四部分 Vue3的响应式原理的开场白 第一个对象 Proxy代理对象
<script> let person = { id: "100908", name: "我是Vue3响应式原理", age: 23, height: "189", } // 内置函数 window.Proxy 代理的对象 const p = new Proxy(person, { // 有人读取了p}身上的某个属性被调用 get(target, proName) { console.log(`有人读取了${proName}身上的某个属性`) console.log(target + "__" + proName) return target[proName] }, // 有人修改了p 或者给p 追加 身上的某个属性被调用 set(target, proName, Value) { console.log(`有人修改了身上的${proName}我要去更新界面了!`) // console.log(target,proName,Value) target[proName] = Value }, // 有人删除了p 身上的某个属性被调用 deleteProperty(target, proName) { console.log(`有人删除了身上的${proName}我要去更新界面了!`) return delete target[proName] }, }) </script>
Vue3的响应式原理的开场白 第一个对象 Proxy代理对象
第五部分 Vue3的响应式原理的开场白 第二个对象 Reflect 对象
<script> // window.Reflect 对象 // Reflect.get(obj,'a') 找到a的值 let obj = { a: 1, b: 2 } // 通过object // Object.defineProperty(obj, 'c', { // get() { // return 4 // } // }) // Object.defineProperty(obj, 'c', { // get() { // return 6 // } // }) const xf= Reflect.defineProperty(obj, 'c', { get() { return 4 } }) console.log(xf) const xf1= Reflect.defineProperty(obj, 'c', { get() { return 6 } }) if(xf1){ console.log("某某操作的内容成功了") }else{ console.log("某某操作的内容失败了") } console.log(xf1) </script>
Vue3的响应式原理的开场白 第二个对象 Reflect 对象
第六部分 Vue响应原理的本质 是第四部分和第五部分的组合体
- 通过Proxy(代理): 拦截对象中任意属性的变化, 包括:属性值的读写、属性的添加、属性的删除等。
- 通过Reflect(反射): 对源对象的属性进行操作。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <h1>Vue3响应式原理的本质</h1> <script> let person = {id: "100908",name: "我是Vue3响应式原理",age: 23,height: "189",} // 内置函数 window.Proxy 代理的对象 const p = new Proxy(person, { // 有人读取了p}身上的某个属性被调用 Reflect. 反射对象 get(target, proName) { console.log(`有人读取了${proName}身上的某个属性`) console.log(target + "__" + proName) return Reflect.get(target,proName) }, // 有人修改了p 或者给p 追加 身上的某个属性被调用 set(target, proName, Value) { console.log(`有人修改了身上的${proName}我要去更新界面了!`) // console.log(target,proName,Value) return Reflect.set(target,proName,Value) }, // 有人删除了p 身上的某个属性被调用 deleteProperty(target, proName) { console.log(`有人删除了身上的${proName}我要去更新界面了!`) return Reflect.deleteProperty(target,proName) }, }) </script> </body> </html>