当前位置:   article > 正文

vue的响应式原理_vue响应式原理

vue响应式原理

Vue 的响应式是通过 Object.defineProperty 对数据进行劫持,并结合发布订阅者模式实现。 Vue 利用 Object.defineProperty 创建一个 observe 来劫持监听所有的属性,把这些属性全部转为 gettersetter。Vue 中每个组件实例都会对应一个 watcher 实例,它会在组件渲染的过程中把使用过的数据属性通过 getter 收集为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
在这里插入图片描述

一、reduce

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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

实际上,reduce方法还有第二个参数,****如果传递了第二个参数,就作为prev的初始值****。同时next就是数组的第一个元素。

<script>

    const total = arr3.reduce(function(pre,next){
		console.log(pre+"----"+next);
		return pre+next;
	},100)
	console.log(total);

</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
//如果不是一个数组而是一个字符串呢
const str="info.address.location";
//console.log(str.split("."))
 const result2 = str.split(".").reduce((newobj,k)=>{
	  return newobj[k];
},person)
console.log(result2);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

二、Object.defineProperty

Object.defineProperty()的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性

Object.defineProperty(obj, prop, desc)
  • 1
  1. obj 需要定义属性的当前对象
  2. prop 当前需要定义的属性名
  3. desc 属性描述符

一般通过为对象的属性赋值的情况下,对象的属性可以修改也可以删除,但是通过Object.defineProperty()定义属性,通过描述符的设置可以进行更精准的控制对象属性。

属性描述符

通过Object.defineProperty()为对象定义属性,有两种形式,且不能混合使用,分别为数据描述符,存取描述符,下面分别描述下两者的区别:

数据描述符 --特有的两个属性(value,writable)
let Person = {
   }
Object.defineProperty(Person, 'name', {
   
   value: 'Lucky',
   writable: true // 是否可以改变
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
存取描述符 --是由一对 getter、setter 函数功能来描述的属性

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
  }
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
数据描述符和存取描述均具有以下描述符
  1. configrable 描述属性是否配置,以及可否删除
  2. enumerable 描述属性是否会出现在for in 或者 Object.keys()的遍历中

**注意:**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)	 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

三、发布-订阅者模式

1.vue响应原理:

vue.js采用数据劫持结合发布-订阅者模式,通过Object.defineProperty()来劫持data中各个属性的setter、getter,在数据变动时,发布消息给订阅者,触发响应的监听回调。

(setter和getter是对象的存储器属性,是一个函数(属性),用来获取和设置值)

2、发布-订阅者模式的作用:

处理一对多的场景,应用于不同情况下的不同函数调用

优点:低耦合性,易于代码维护;

缺点:若订阅的消息未发生,需消耗一定的时间和内存。

发布订阅者模式:

其定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知

在这里插入图片描述

举个栗子

这里面以微信公众号为例:

  • 假如用户大脚订阅了 胡吃海喝这个公众号,那么当公众号胡吃海喝推送消息的时候,用户大脚就会收到相关的推送,点开可以查看推送的消息内容。
  • 但是公众号胡吃海喝并不关心订阅的它的是男人、女人还是未成年,它只负责发布自己的主体,只要是订阅公众号的用户均会收到该消息。
  • 作为用户大脚,不需要时刻打开手机查看公众号胡吃海喝是否有推动消息,因为在公众号推送消息的那一刻,大脚就会收到相关推送。
  • 当然了,用户大脚如果不想继续关注公众号胡吃海喝,那么可以取消关注,取关以后,公众号胡吃海喝再推送消息,大脚就无法收到了。

还有一个生活中的栗子,就是买房子的情景。

vue的发布订阅模式可以用下图简单描述:

在这里插入图片描述
接下来用代码实现简单的发布订阅者

//收集依赖/收集订阅
  class Dep{
   
	  constructor(){
   
		  //这个subs数组,用来存放所有订阅者的信息
		  this.subs=[]
	  }
	  //向subs数组中,添加订阅者的信息
	  addSubs(watcher){
   
	  	  this.subs.push(watcher)
	  }
	  //发布通知的方法
	  notify(){
   
		 this.subs.forEach((watcher)=>watcher.update()) 
	  }
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/259120
推荐阅读
相关标签
  

闽ICP备14008679号