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

发布时间:2024年01月23日

回答思路: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执行更新方法 
	}, 
}); 
}
文章来源:https://blog.csdn.net/laowang357/article/details/135769922
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。