vue2面试题:什么是双向数据绑定

本文详细解释了Vue2中双向数据绑定的概念、原理,涉及Dep、Observer、Compile和Watcher的角色,并通过实例展示如何在构造函数中实现响应式处理和数据绑定的过程。
摘要由CSDN通过智能技术生成

回答思路:1.什么是双向绑定–>2.双向数据绑定的原理–>3.如何实现双向数据绑定

1.什么是双向绑定

把Model绑定到View上为单向绑定,双向绑定就是在单向绑定的基础上,用户更新了view后model也会随之更新

2.双向数据绑定的原理

Dep:属性订阅器
Observer:监听器(对所有属性进行监听)
Compile:解析器(对每个节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数)
Watcher:观察者(负责建立Vue实例属性与视图之间的联系,在属性值发生变化时更新视图)

vue.js采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter和getter,在数据发生变动时发布消息给订阅者,触发相应的监听回调,分为一下几个步骤:
在这里插入图片描述
(1)对需要监听的数据对象进行递归遍历,包括子属性对象的属性,都加上setter、getter,改变其中值就会触发setter,Observer就能监听到了
(2)compile解析模板指令,将模板指令替换成数据,然后初始化渲染页面视图,绑定更新函数,添加订阅者,一旦有数据变化就通知watcher进行更新
(3)watcher是observer和compile的通信桥梁,主要作用:1.自身实例化时往Dep中添加订阅者2.自身必须要有一个update()函数3.等属性变动时Dep会调用dep.notify()通知watcher,watcher调用自身的update()方法进行更新,并触发compile绑定的回调函数

3.如何实现双向数据绑定

来一个构造函数:执行初始化,对data执行响应化处理

class Vue { 
 constructor(options) { 
 this.$options = options; 
 this.$data = options.data; 
 
 // 对data选项做响应式处理 
 observe(this.$data); 
 
 // 代理data到 vm上 
 proxy(this); 
 
 // 执行编译
 new Compile(options.el, this); 
 } 
}

在observer中对data响应化的具体操作:

function observe(obj) { 
	if (typeof obj !== "object" || obj == null) { 
		return; 
	} 
	new Observer(obj); 
} 
 
class Observer { 
	constructor(value) { 
	this.value = value; 
	this.walk(value); 
} 
walk(obj) { 
	Object.keys(obj).forEach((key) => { 
	defineReactive(obj, key, obj[key]); 
	}); 
 } 
}

编译compile

对每个元素节点的指令进行扫描和解析,根据指令替换数据,以及绑定相应的更新函数

class Compile { 
	constructor(el, vm) { 
		this.$vm = vm; 
		this.$el = document.querySelector(el); //获取dom 
		if (this.$el) { 
			this.compile(this.$el); 
		} 
 } 
 compile(el) { 
 	const childNodes = el.childNodes; 
 	Array.from(childNodes).forEach((node) => { // 
 	if (this.isElement(node)) { // 
 	console.log(" " + node.nodeName); 
} else if (this.isInterpolation(node)) { 
	console.log(" " + node.textContent); // 判断是否为插值文本{{}} 
 } 
 if (node.childNodes && node.childNodes.length > 0) { //判断是否有子元素 
 
	this.compile(node); // 对子元素进行递归遍历
	} 
}); 
} 
isElement(node) { 
	return node.nodeType == 1; 
} 
isInterpolation(node) { 
	return node.nodeType == 3 && /\{\{(.*)\}\}/.test(node.textContent); 
 } 
}

依赖收集

依赖收集,创建Dep实例

function defineReactive(obj, key, val) { 
	this.observe(val); 
	const dep = new Dep(); 
	Object.defineProperty(obj, key, { 
		get() { 
			Dep.target && dep.addDep(Dep.target);// Dep.target 就是Watcher实例 
			return val; 
		}, 
		set(newVal) { 
			if (newVal === val) return; 
			dep.notify(); // 通知dep执行更新方法 
	}, 
}); 
}
  • 16
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王 歪歪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值