简单实现Vue数据双向绑定

前言

在现在的mvvm框架中, 有一个很普遍的功能 就是数据的双向绑定, 即响应式。那么这样的功能是怎样的实现的呢? 在阅读了染陌同学的《剖析 Vue.js 内部运行机制》后, 在这里复习一下。

实现

原理比较简单, 就是通过Object.defineProperty将需要响应式的对象的属性设置为get和set, 并在get所在闭包中, 通过dep对象进行依赖收集; 在set中调用dep中的notify方法,更新收集来的watcher对象(遍历watchers数组, 调用watcher的更新方法)。

Dep类——用于收集的类

class Dep {
	constructor() {
		this.subs = []//用于存放watcher对象的数组
	}
	addSub (sub) {
		this.subs.push(sub)
	}
	notify(){
		this.subs.forEach(sub=>{
			sub.update()	
		})
	}
}

Dep.target = null

Watcher类——用于更新组件视图的类

class Watcher {
	constructor(){
		Dep.target = this
	}
	update(){
		console.log("视图更新了")
	}
}

defineReactive函数

function defineReactive(obj, key, val) {
	const dep = new Dep()
	Object.defineProperty(obj, key, {
		enumerable: true,
		configurable: true,
		get: function reactiveGetter() {
			dep.addSub(Dep.target)
			return val	
		},
		set: function reactiveSetter(){
			if(newVal === val) return
			val = newVal
			dep.notify()	
		}
	})
}

observer方法

function observer(value) {
	if(!value || (typeof value !== 'object')) {
		return	
	}
	Object.keys(value.forEach).forEach(key => {
		defineReactive(value, key, value[key])	
	})
}

简洁版Vue构造函数

class Vue {
	constructor(options) {
		this._data = options.data
		observer(this._data)
		new Watcher();
	}
}

最后

let o = new Vue({
   data: {
   	test: 'test'
   }
})

以上new了一个Vue对象,并且this._data已经被响应式了。

o._data.test//需要向get一下, 让getter所在的闭包中的dep对其收集

o._data.test = 'hello' //执行setter里的dep.notify进行更新, 最后会调用watcher中的update函数,更新视图
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值