赞
踩
Vue 的响应式是通过 Object.defineProperty
对数据进行劫持,并结合发布订阅者模式实现。 Vue 利用 Object.defineProperty
创建一个 observe
来劫持监听所有的属性,把这些属性全部转为 getter
和 setter
。Vue 中每个组件实例都会对应一个 watcher
实例,它会在组件渲染的过程中把使用过的数据属性通过 getter
收集为依赖。之后当依赖项的 setter
触发时,会通知 watcher
,从而使它关联的组件重新渲染。
1.数值的累加
作用:将****前一项*和*后一项****的值进行运算,返回累积的结果
格式:数组.reduce(function(prev,next){…})
其中,prev表示前一项,next表示后一项。
运算规则:
默认情况下,会把数组的第一个元素作为prev的初始值。
每循环一次,把累积的结果赋给prev,next就变为下一个数组元素
var arr3 = [10,22,23,25,50];
const total = arr3.reduce(function(pre,next){
console.log(pre+"----"+next);
return pre+next;
})
console.log(total);
实际上,reduce方法还有第二个参数,****如果传递了第二个参数,就作为prev的初始值****。同时next就是数组的第一个元素。
<script>
const total = arr3.reduce(function(pre,next){
console.log(pre+"----"+next);
return pre+next;
},100)
console.log(total);
</script>
2.链式获取对象的值
const person={ name:"尼古拉斯赵四", info:{ address:{ location:"东北铁岭", work:"二人转" } } } const arrs=["info","address","location"]; const result=arrs.reduce((newobj,k)=>{ console.log(newobj) return newobj[k] },person) console.log(result);
//如果不是一个数组而是一个字符串呢
const str="info.address.location";
//console.log(str.split("."))
const result2 = str.split(".").reduce((newobj,k)=>{
return newobj[k];
},person)
console.log(result2);
Object.defineProperty()
的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性
Object.defineProperty(obj, prop, desc)
一般通过为对象的属性赋值的情况下,对象的属性可以修改也可以删除,但是通过Object.defineProperty()定义属性,通过描述符的设置可以进行更精准的控制对象属性。
通过Object.defineProperty()为对象定义属性,有两种形式,且不能混合使用,分别为数据描述符,存取描述符,下面分别描述下两者的区别:
let Person = {
}
Object.defineProperty(Person, 'name', {
value: 'Lucky',
writable: true // 是否可以改变
})
get
:一个给属性提供getter
的方法,如果没有getter
则为undefined
。该方法返回值被用作属性值。默认为undefined
。
set
:一个给属性提供setter
的方法,如果没有setter
则为undefined
。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认值为undefined
。
let Person = {}
let temp = null
Object.defineProperty(Person, 'name', {
get: function () {
return temp
},
set: function (val) {
temp = val
}
})
**注意:**configurable: false 时,不能删除当前属性,且不能重新配置当前属性的描述符(但是可以把writable的状态由true改为false,但是无法由false改为true),但是在writable: true的情况下,可以改变value的值。
其他属性:Object.seal()、Object.freeze()不再说。
configurable: true时,可以删除当前属性,可以配置当前属性所有描述符。
var fun={ name:"kelly", age:'123' } var funage='哈哈'; Object.defineProperty(fun,'address',{ get(){ return funage; }, set(val){ console.log('触发fun') funage=val; } }) // fun.name="张三"; // console.log(fun); // fun.age=12; // console.log(fun.age) fun.address="中山西路" console.log(fun.address)
vue.js采用数据劫持结合发布-订阅者模式,通过Object.defineProperty()来劫持data中各个属性的setter、getter,在数据变动时,发布消息给订阅者,触发响应的监听回调。
(setter和getter是对象的存储器属性,是一个函数(属性),用来获取和设置值)
处理一对多的场景,应用于不同情况下的不同函数调用
优点:低耦合性,易于代码维护;
缺点:若订阅的消息未发生,需消耗一定的时间和内存。
发布订阅者模式:
其定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知
举个栗子
这里面以微信公众号为例:
大脚
订阅了 胡吃海喝
这个公众号,那么当公众号胡吃海喝
推送消息的时候,用户大脚
就会收到相关的推送,点开可以查看推送的消息内容。胡吃海喝
并不关心订阅的它的是男人、女人还是未成年,它只负责发布自己的主体,只要是订阅公众号的用户均会收到该消息。大脚
,不需要时刻打开手机查看公众号胡吃海喝
是否有推动消息,因为在公众号推送消息的那一刻,大脚
就会收到相关推送。大脚
如果不想继续关注公众号胡吃海喝
,那么可以取消关注,取关以后,公众号胡吃海喝
再推送消息,大脚
就无法收到了。还有一个生活中的栗子,就是买房子的情景。
vue的发布订阅模式可以用下图简单描述:
接下来用代码实现简单的发布订阅者
//收集依赖/收集订阅 class Dep{ constructor(){ //这个subs数组,用来存放所有订阅者的信息 this.subs=[] } //向subs数组中,添加订阅者的信息 addSubs(watcher){ this.subs.push(watcher) } //发布通知的方法 notify(){ this.subs.forEach((watcher)=>watcher.update()) }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。