vue的双向数据绑定原理

一、绪论
相信大多数前端开发者在找工作的时候都会问到vue的双向数据的绑定原理
很多人都会说:vue内部使用es5的方法 Object.defineProperty()的方法进行属性拦截,把data对象的每个数据的读写通过调用getter和setter方法,当数据发生改变时,通知视图更新更新。
显然这个是知道的只是大概
2、分析mvvm
所谓的 mvvm双向数据绑定,就是通过数据改变通知视图更新,视图变化更新数据
在这里插入图片描述
两个问题
1)数据变成可以观测的
2)把对象的每一个属性都变得可观测
3)数据变化怎么更新视图
4)视图变化怎么更新数据
二、问题一:解决怎么使数据变得可以观测、
监测数据对象的变化
es5中的Object.defineProperty()方法 会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性并返回这个对象
代码说话

const  shop={
	“produceName”:‘华为’,
		  “price”:10000
}

上述对象我们
可以读 shop.produceName
可以写 shop.produceName=‘苹果’
问题来了:但是我们并不知道它 什么时候读的,什么时候写的
通过es5的Object.defineProperty()进行改写

   const shop={}
   const   price=10000
   Object.defineproPerty( shop ,'price',{
	get(){
		console.log('该方法是当price被读取的时候触发') 
		return val   //把price对应的值return出来  1000
	},
	set(newVal){
		console.log('price数据发生变化时执行')
		val=newVal  //当修改了老的price的val时 再次打印price 就是新的数据
	}
})

//上述是通过 Object.defineProperty()方法 给shop的空对象 定义了一个price属性,并把这个属性的读和写 挂在到了 对象中的get()和set()方法中进行拦截,每当你操作数据的时候就会触发 这两个函数
问题一已决定
三、解决问题二:把对象的每一个属性都变成可观测的数据

  function observable(obj){
	  if(!obj ||typeof obj!=='object'){
		//如果obj不存在 或者 obj的类型不等于 object  
		return}
	  const keys=Object.keys(obj) //获取到所有的key值  返回key组成的数组
	  keys.forEach((key)=>{
		//把每一项都变成可观测的属性
		defineReactive(obj,key,obj[key])
	})
	return obj
  }
  //现在定义一个可观测的对象
const obj=observable({
	name:'小米',
	age:23
}

obj 的两个属性都是可观测的了

将一个对象变成可观测的对象

//obj 对象
//key 对象的ket
//val 对象的val
function defineReactive(obj,key,val){
	Object.defineProperty(obj,key,{
		get(val){
		console.log('属性被读取了')
		return val
	}set(newval){
	console.log('属性被修改了')
	var=newval
}
})
}

四、通过依赖 创建专门收集改变的数据的容器
数据的可观测完成之后,我们要收集已经改变的数据,通知视图更新
其实发布订阅者模式就是这个道理
数据变化 就是“发布者”
收集数据通知试图就是“订阅者”
now 我们需要创建一个依赖 收集容器
消息订阅器 Dep 用来容纳所有的“订阅者”(被改变的数据)
这个订阅器Dep主要负责收集订阅者 ,数据一旦变化,就会执行对应订阅者的更新函数
创建订阅器Dep

 class Dep{
constructor(){
this.subs=[]
},
//添加订阅者
addSub(sub){
this.subs.push(sub);
},
//判读是否添加订阅者
depend(){
	if(Dep.target){
	this.addSub(Dep.target)
	}
},
//通知订阅者 更新
notify(){
	this.subs.forEach((sub=>{
	sub.update()
	}))
}
} 

五、把订阅器嵌入defineReactive 函数 中

function defineReactive(obj,key,val){
const dep=new Dep(); //实例化订阅器
Object.defineProperty (obj,key,{
get (){
dep.depend();// 添加订阅者
console.log(‘数据被读取时自动触发’)
return val
},
set(newVal){
val=newVal;
console.log(‘数据改变时触发’)
dep.notify()
}
})
}

分析:四,五
上面定义了一个订阅器Dep类,该类里面 定义了一些属性和方法,这里注意 它有一个静态属性target,这是一个全局唯一的Watcher,为了 同一时间内只能有一个全局的Watcher被计算,另外他的自身属性subs也是Watcher的数组

上述将订阅器Dep添加订阅者的操作设计在getter里面,这是为了让Wacher 初始化时进行触发,因此需要判断是否添加订阅者。在setter函数里面,如果数据变化,就会去通知所有订阅者,订阅者们就会去执行对应的更新的函数,
现在订阅器Dep设计完毕 接下来 设置订阅者 Watcher
六、创建订阅者 (未完待续)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值