文档章节

Vue.js双向绑定的实现原理

别人说我名字很长
 别人说我名字很长
发布于 2016/12/10 00:08
字数 359
阅读 40
收藏 0
<!DOCTYPE html>
<html>
<head>
	<title>Vue.js双向绑定的实现原理</title>
</head>
<body>
<div id="app">
	<input type="text" v-model="text">
	{{ text }}
</div>

<script type="text/javascript">


//订阅者
function Dep(){
	this.subs = [];
}

Dep.prototype = {
	addSub:function(sub){
		this.subs.push(sub);
	},
	notify:function(){
		this.subs.forEach(function(sub){
			sub.update();
		});
	}
}

//发布者
function Watcher (vm, node, name) {
	Dep.target = this;	
	this.name = name;
	this.node = node;
	this.vm = vm;
	this.update();
	Dep.target = null;
}

Watcher.prototype = {
	update: function () {
		this.get();
		this.node.nodeValue = this.value;
	},
	// 获取data中的属性值
	get: function () {
		this.value = this.vm[this.name]; // 触发相应属性的get
	}
}


//对象访问器
function defineReactive(obj,key,val) {
	var dep = new Dep();
	Object.defineProperty(obj,key,{
		get:function(){
			// 添加订阅者watcher到主题对象Dep
			if(Dep.target)dep.addSub(Dep.target);
			console.log(dep.subs)
			return val;
		},
		set:function(newVal){
			if(newVal === val) return;
			val=newVal;
			//作为发布者发布通知
			dep.notify();
			console.log(val);
		}
	})
}

//观察者,观察data对象的变更,使用Object.defineProperty添加订阅者和发布通知
function observe(obj,vm){
	Object.keys(obj).forEach(function(key){
		defineReactive(vm,key,obj[key]);
	});
}

//编译方法
function compile(node,vm){
	var reg = /\{\{(.*)\}\}/;

	//节点类型为元素
	if(node.nodeType === 1){
		var attr = node.attributes;
		for(var i=0;i<attr.length;i++){
			if(attr[i].nodeName == 'v-model'){
				var name = attr[i].nodeValue;
				node.addEventListener('input',function(e){
					vm[name] = e.target.value;
				});
				node.value = vm[name];
				node.removeAttribute('v-model');
			}
		}
	}

	//节点类型为text
	if(node.nodeType ===3){
		if(reg.test(node.nodeValue)){
			var name = RegExp.$1;
			name = name.trim();
			new Watcher(vm,node,name);
		}
	}
}

//使用DocumentFragment劫持挂载的目标节点
function nodeToFragment(node,vm){
	var flag = document.createDocumentFragment();
	var child;
	while(child = node.firstChild){
		compile(child,vm);
		flag.append(child);
	}
	return flag;
}

function Vue(options){
	this.data = options.data;
	var data = this.data;

	observe(data,this);

	var id = options.el;
	var dom = nodeToFragment(document.getElementById(id),this);
	//编译完成后将dom返回到app中
	document.getElementById(id).appendChild(dom);
}

var vm = new Vue({
	el:'app',
	data:{
		text:'hello world'
	}
})
</script>
</body>
</html>

 

本文转载自:http://www.cnblogs.com/kidney/p/6052935.html?utm_source=gold_browser_extension

共有 人打赏支持
别人说我名字很长
粉丝 55
博文 254
码字总数 103692
作品 0
济南
程序员
深入理解Vue的watch实现原理及其实现方式

理解Vue中Watch的实现原理和方式之前,你需要深入的理解MVVM的实现原理,如果你还不是很理解,推荐你阅读我之前的几篇文章: 彻底搞懂Vue针对数组和双向绑定(MVVM)的处理方式 vue.js源码解读...

wangweianger
05/14
0
0
Vue和React数据绑定对比

在数据绑定上来说,vue的特色是双向数据绑定,而在react中是单向数据绑定。 一 单向和双向数据绑定其实不是完全没关系的 表单的双向绑定,说到底不过是 (value 的单向绑定 + onChange 事件侦...

pattyzzh
05/14
0
0
西安电话面试:谈谈Vue数据双向绑定原理,看看你的回答能打几分

最近我参加了一次来自西安的电话面试(第二轮,技术面),是大厂还是小作坊我在这里按下不表,先来说说这次电面给我留下印象较深的几道面试题,这次先来谈谈Vue的数据双向绑定原理。 情景再现...

闰土大叔
04/25
0
0
个人理解Vue和React区别

监听数据变化的实现原理不同 Vue 通过 getter/setter 以及一些函数的劫持,能精确知道数据变化,不需要特别的优化就能达到很好的性能 React 默认是通过比较引用的方式进行的,如果不优化(P...

binbinsilk
09/06
0
0
关于Vue和React区别的一些笔记

这篇文章记录我在使用Vue和React的时候,对他们的不同之处的一些思考,不仅局限于他们本身,也会包括比如 等经常搭配使用的工具。因为涉及到的内容很多,可能下面的每一个点都能写成一篇文章...

言川
07/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Docker Compose 原理

Docker 的优势非常明显,尤其是对于开发者来说,它提供了一种全新的软件发布机制。也就是说使用 docker 镜像作为软件产品的载体,使用 docker 容器提供独立的软件运行上下文环境,使用 dock...

Java干货分享
18分钟前
0
0
解决过滤器中设置cookie无效的问题

解决过滤器中设置cookie无效的问题 代码现场 filterChain.doFilter(sessionSyncRequestWrapper, response);Cookie emailCook = WebServletUtil.getSelectedCookie(request.getCookies(), ......

黄威
29分钟前
0
0
Hbase Schema 设计注意事项及最佳实践总结

一个列族的所有列在硬盘上存放在一起,使用这个特性可以把不同访问模式的列放在不同列族,以便隔离它们。这也是HBase被称为面向列族的存储(column-family-oriented store)的原因。 1、RowKe...

PeakFang-BOK
42分钟前
1
0
t-io给群组成员内置排序

1、实现比较器Comparator<ChannelContext> package xxx;import java.util.Comparator;import java.util.Objects;import java.util.Set;import java.util.TreeSet;import or......

talent-tan
45分钟前
2
0
px、em、rem 区别及作用

原文 起因: 一开始是为了解决页面放大时,字体不跟着放大的 bug。现在多用用于统一规范。 概念: 任意浏览器的默认字体高都是16px。所有未经调整的浏览器都符合: 1em=16px。那么12px=0.75em...

lemos
54分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部