vue的响应式原理

本文深入探讨Vue的响应式原理,主要涉及reduce、Object.defineProperty及其属性描述符、发布-订阅者模式在Vue中的应用,以及如何简单实现双向数据绑定。Vue通过Object.defineProperty劫持数据并结合发布-订阅者模式,监听属性变化,实现组件的高效更新。
摘要由CSDN通过智能技术生成

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);

实际上,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()的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性

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

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

属性描述符

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

数据描述符 --特有的两个属性(value,writable)
let Person = {
   }
Object.defineProperty(Person, 'name', {
   
   value: 'Lucky',
   writable: true // 是否可以改变
})
存取描述符 --是由一对 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. 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.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()) 
	  }
  }
  
  //订阅者的类
  
  • 6
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值