每日一题之Vue数据劫持原理是什么? | 您所在的位置:网站首页 › vue数据劫持 › 每日一题之Vue数据劫持原理是什么? |
什么是数据劫持?
定义: 数据劫持,指的是在访问或者修改对象的某个属性时,通过一段代码拦截这个行为,进行额外的操作或者修改返回结果。 简单地说,就是当我们 触发函数的时候 动一些手脚做点我们自己想做的事情,也就是所谓的 "劫持"操作 数据劫持的两种方案: Object.defineProperty Proxy 1).Object.defineProperty 语法:Object.defineProperty(obj,prop,descriptor) 参数: obj:目标对象 prop:需要定义的属性或方法的名称 descriptor:目标属性所拥有的特性可供定义的特性列表: value:属性的值 writable:如果为false,属性的值就不能被重写。 get: 一旦目标属性被访问就会调回此方法,并将此方法的运算结果返回用户。 set:一旦目标属性被赋值,就会调回此方法。 configurable:如果为false,则任何尝试删除目标属性或修改属性性以下特性(writable, configurable, enumerable)的行为将被无效化。 enumerable:是否能在for…in循环中遍历出来或在Object.keys中列举出来。 例子在Vue中其实就是通过Object.defineProperty来劫持对象属性的setter和getter操作,并“种下”一个监听器,当数据发生变化的时候发出通知,如下: var data = { name:'test'} Object.keys(data).forEach(function(key){ Object.defineProperty(data,key,{ enumerable:true, configurable:true, get:function(){ console.log('get'); }, set:function(){ console.log('监听到数据发生了变化'); } }) }); data.name //控制台会打印出 “get” data.name = 'hxx' //控制台会打印出 "监听到数据发生了变化"上面的这个例子可以看出,我们完全可以控制对象属性的设置和读取。在Vue中,在很多地方都非常巧妙的运用了Object.defineProperty这个方法,具体用在哪里并且它又解决了哪些问题,下面就简单的说一下: 监听对象属性的变化它通过observe每个对象的属性,添加到订阅器dep中,当数据发生变化的时候发出一个notice。 相关源代码如下:(作者采用的是ES6+flow写的,代码在src/core/observer/index.js模块里面) export function defineReactive ( obj: Object, key: string, val: any, customSetter?: Function ) { const dep = new Dep()//创建订阅对象 const property = Object.getOwnPropertyDe述 //属性的描述特性里面如果configurable为false则属性的任何修改将无效 if (property && property.configurable === false) { return }scriptor(obj, key)//获取obj对象的key属性的描 // cater for pre-defined getter/setters const getter = property && property.get const setter = property && property.set let childOb = observe(val)//创建一个观察者对象 Object.defineProperty(obj, key, { enumerable: true,//可枚举 configurable: true,//可修改 get: function reactiveGetter () { const value = getter ? getter.call(obj) : val//先调用默认的get方法取值 //这里就劫持了get方法,也是作者一个巧妙设计,在创建watcher实例的时候,通过调用对象的get方法往订阅器dep上添加这个创建的watcher实例 if (Dep.target) { dep.depend() if (childOb) { childOb.dep.depend() } if (Array.isArray(value)) |
CopyRight 2018-2019 实验室设备网 版权所有 |