文档章节

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

别人说我名字很长
 别人说我名字很长
发布于 2016/12/10 00:08
字数 359
阅读 37
收藏 0
点赞 0
评论 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
博文 243
码字总数 97391
作品 0
济南
程序员
深入理解Vue的watch实现原理及其实现方式

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

wangweianger ⋅ 05/14 ⋅ 0

Vue和React数据绑定对比

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

pattyzzh ⋅ 05/14 ⋅ 0

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

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

闰土大叔 ⋅ 04/25 ⋅ 0

这一次 彻底搞懂Vue针对数组和双向绑定(MVVM)的处理方式

欢迎关注我的博客:github.com/wangweiange… Vue内部实现了一组观察数组的变异方法,例如:push(),pop(),shift()等。 Object.definePropert只能把对象属性改为getter/setter,而对于数组的...

wangweianger ⋅ 05/12 ⋅ 0

面试官: 实现双向绑定Proxy比defineproperty优劣如何?

面试官系列(4): 实现双向绑定Proxy比defineproperty优劣如何? 往期 面试官系列(1): 如何实现深克隆 面试官系列(2): Event Bus的实现 面试官系列(3): 前端路由的实现 前言 双向绑定其实已经是...

寻找海蓝96 ⋅ 05/03 ⋅ 0

Vue学习系列一 —— MVVM响应式系统的基本实现原理

MVVM是什么 MVVM是Model-View-ViewModel的简写。它模式是MVC—>MVP—>MVVM的进化版。 Model负责用JavaScript对象表示,View负责UI界面显示,两者做到了最大限度的分离。 而把Model和View关联...

浩3108 ⋅ 05/23 ⋅ 0

js技巧:十几行的代码实现vue.watch

最近忙得狗一样,有一段时间没有更新了,虽然是僵尸博主,但是有点小收获还是要来唠叨一下的。 相信很多的用vue的人都知道vue双向绑定的原理建立在,给属性绑定了getter和setter,在属性被改...

JasonWild ⋅ 05/22 ⋅ 0

太原面经分享:如何在vue面试环节,展示你晋级阿里P6+的技术功底?

前言 一年一度紧张刺激的高考开始了,与此同时,我也没闲着,奔走在各大公司的前端面试环节,不断积累着经验,一路升级打怪。 最近两年,太原作为一个准二线城市,各大互联网公司的技术栈也在...

闰土大叔 ⋅ 06/08 ⋅ 0

JavaScript 开发框架横向比对(Vue、React 和 Angular)

1 背景比对 MIT license 与 BSD-license 之间的区别是:MIT license 允许衍生软件加上我们自己的名字做推广,而 BSD license 不可以。 MVVM(Model-View-ViewModel):将其中的View 的状态和...

deniro ⋅ 05/30 ⋅ 0

Vue.js视频教程

Vue.js 1.0 免费中文视频教程在线观看和网盘下载地址收集 原文地址:http://phpecshop.blog.51cto.com/6296699/1834208 NideShop:基于Node.js+MySQL开发的高仿网易严选开源B2C商城(微信小...

ch10mmt ⋅ 2016/08/04 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Docker系列教程28-实战:使用Docker Compose运行ELK

原文:http://www.itmuch.com/docker/28-docker-compose-in-action-elk/,转载请说明出处。 ElasticSearch【存储】 Logtash【日志聚合器】 Kibana【界面】 答案: version: '2'services: ...

周立_ITMuch ⋅ 30分钟前 ⋅ 0

使用快嘉sdkg极速搭建接口模拟系统

在具体项目研发过程中,一旦前后端双方约定好接口,前端和app同事就会希望后台同事可以尽快提供可供对接的接口方便调试,而对后台同事来说定好接口还仅是个开始、设计流程,实现业务逻辑,编...

fastjrun ⋅ 55分钟前 ⋅ 0

PXE/KickStart 无人值守安装

导言 作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装。 常规的办法有什么? 光盘安装系统 ===> 一...

kangvcar ⋅ 昨天 ⋅ 0

使用Puppeteer撸一个爬虫

Puppeteer是什么 puppeteer是谷歌chrome团队官方开发的一个无界面(Headless)chrome工具。Chrome Headless将成为web应用自动化测试的行业标杆。所以我们很有必要来了解一下它。所谓的无头浏...

小草先森 ⋅ 昨天 ⋅ 0

Java Done Right

* 表示难度较大或理论性较强。 ** 表示难度更大或理论性更强。 【Java语言本身】 基础语法,面向对象,顺序编程,并发编程,网络编程,泛型,注解,lambda(Java8),module(Java9),var(...

风华神使 ⋅ 昨天 ⋅ 0

Linux系统日志

linux 系统日志 /var/log/messages /etc/logrotate.conf 日志切割配置文件 https://my.oschina.net/u/2000675/blog/908189 logrotate 使用详解 dmesg 命令 /var/log/dmesg 日志 last命令,调......

Linux学习笔记 ⋅ 昨天 ⋅ 0

MVC——统一报文格式的异常处理响应

在我们写controller层的时候,常常会有这样的困惑,如果需要返回一个数据是,可能为了统一回去构造一个类似下列的数据格式: { status:true, msg:"保存成功!", data:[]} 而且在写...

alexzhu592 ⋅ 昨天 ⋅ 0

[知乎]SSH框架

网上图书馆管理系统包括管理员管理和图书管理,图书借阅,查询模块等等,网上商城包括前台页面和后台管理页面,两个都是以前别人的实际项目,只是别人用的不是SSH,我把他们改用SSH了,除了S...

颖伙虫 ⋅ 昨天 ⋅ 0

android -------- 打开本地浏览器或指定浏览器加载,打电话,打开第三方app

开发中常常有打开本地浏览器加载url或者指定浏览器加载, 还有打开第三方app, 如 打开高德地图 百度地图等 在Android程序中我们可以通过发送隐式Intent来启动系统默认的浏览器。 如果手机本身...

切切歆语 ⋅ 昨天 ⋅ 0

linux 安装docker

通过以下命令下载安装docker wget -qO- https://get.docker.com | sh 执行以上命令后输出以下内容说明安装成功,注意红框中的内容,docker安装成功后默认只有root能使用,红框中给出的提示是...

haoyuehong ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部