v-model双向绑定原理

介绍

数据双向绑定也就是说,模型数据变化更新视图,视图变化更新模型数据。
v-model 实现的原理是采用 数据劫持 + 发布者-订阅者模式 实现。

效果图

最终效果图

HTML部分

<div id="app">
	<input type="text" v-model="msg" />
</div>

JavaScript部分

// 核心类
class MyApp {
	constructor({el, data}) {
		this.container = document.querySelector(el);
		this.data = data;

		// 初始化数据
		this.initData();
			
		// 初始化视图
		this.initView();
	}

	initData() {
		const dep = new Dep();
		Object.entries(this.data).forEach(([key, value]) => {
			Object.defineProperty(this, key, {
				configurable: true,
				enumerable: true,
				get() {
					Dep.target && dep.addWatcher(Dep.target);
					return value;
				},
				set(newValue) {
					value = newValue;
					dep.notify(); // 通知变化。
				}
			})
		})
	}

	initView() {
		const nodes = this.container.querySelectorAll('[v-model]'); // 获取所有绑定v-model自定义属性的Dom节点。
		nodes.forEach(node => {
			const key = node.getAttribute('v-model'); // 获取自定义属性绑定的值。
			// 创建观察者
			new Watcher(this, key, () => {
				node.value = this[key];
			});
			
			node.value = this[key]; // 初始赋值。
			
			node.addEventListener('input', e => {
				this[key] = e.target.value; // 添加键入事件,如果改变则修改模型中对应数据的值。
			}, false);
		})
	}
}

// 订阅者,因为有n个观察者所以需要订阅者统一进行管理。
class Dep {
	constructor() {
		this.watchers = []}// 添加观察者
	addWatcher(watcher) {
		this.watchers.push(watcher);
	}
	
	// 数据变化通知观察者。
	notify() {
		this.watchers.forEach(watcher => {
			watcher.update();
		})
	}
}

// 观察者
class Watcher {
	constructor(vm, key, callback) {
		this.vm = vm;
		this.key = key;
		this.callback = callback;
		Dep.target = this;
		this.value = this.vm[this.key]; // 为了初始化数据时创建对应的观察者,需要获取数据以达到调用definePropety()的get方法。
		Dep.target = null;
	}

	// 修改视图
	update() {
		this.callback();
	}
}

// 使用
const vm = new MyApp({
	el: '#app',
	data: {
		msg: '123'	
	}
})

参考视频:手动实现MVVM双向绑定(v-model原理)

疑问:Dep.target = this 是什么作用,恳请大佬解答。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值