Vue双向绑定实现原理demo
一.index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Vue双向绑定原理</title>
<script src="js/myVue.js"></script>
</head>
<body>
<div id="myApp">
<input type="text" style="width:200px" v-model="value">
<button v-on:click="fn">清空</button>
<div v-text="value"></div>
<div v-html="value"></div>
</div>
</body>
<script>
var vm = new MyVue({
el: "#myApp",
data: {
value: "<h1>VUE</h1>"
},
methods: {
fn() {
this.value = "";
}
}
})
</script>
</html>
二.myVue.js
function MyVue(options){// 创建构造函数MyVue,并接收对象结构体options
this.$el=document.querySelector(options.el);// 指定挂载元素
this.$data=options.data;// 存放你的数据内容
this.$methods=options.methods;// 存放设你的方法
this.binding={};// 所有数据相关的订阅者对象都存放于此。最终结构为{数据属性:[订阅者对象,订阅者对象……]}
this.observer();// 调用观察者,对数据进行劫持
this.compile(this.$el);// 对元素指令进行解析,订阅者也是在此处创建的
}
MyVue.prototype.observer=function(){// 观察者
let value="";// 定义用于存放数据属性值的变量value
for(let key in this.$data){ // 遍历数据对象
value=this.$data[key];// 对象属性值
this.binding[key]=[];// 数据订阅者初始化,是一个数组,
let binding=this.binding[key];// 用于存放本数据相关的所有订阅者,初始为[]
Object.defineProperty(this.$data,key,{// 开始设置劫持
get(){
return value;// 读取值为value
},
set(v){// v为设置的值
if(v!==value){// 当设置的值与当前值不相等时
value=v;// 将读取值更新为v
binding.forEach(watcher=>{
watcher.update();// 通知与本数据相关的订阅者们进行视图更新
})
}
}
})
}
}
MyVue.prototype.compile=function(el){// 解析器
let nodes=el.children;// 获得所有子节点
for(let i=0;i<nodes.length;i++){// 对子节点进行遍历
let node=nodes[i];// 具体节点
if(node.children.length>0)// 判断是否具有子节点
this.compile(node);// 如果有子点进行递归操作
if(node.hasAttribute("v-on:click")){// 该节点是否拥有v-on指令
let attrVal=node.getAttribute("v-on:click");// 得到指令对应的方法名
// 为元素绑定click事件,事件方法为$methods下的方法,并将其this指向this.$data
node.addEventListener("click",this.$methods[attrVal].bind(this.$data))
}
if(node.hasAttribute("v-model")){// 该节点是否拥有v-model指令
let attrVal=node.getAttribute("v-model");// 获得指令对应的数据属性
node.addEventListener("input",((i)=>{// 为指令添加input事件
this.binding[attrVal].push(new Watcher(node,"value",this,attrVal));// 为该数据添加订阅者
return ()=>{
this.$data[attrVal]=nodes[i].value;// 更新$data的属性值,会在观察者中进行劫持
}
})(i))
}
if(node.hasAttribute("v-html")){// 该节点是否拥有v-html指令
let attrVal=node.getAttribute("v-html");// 获得指令对应的数据属性
this.binding[attrVal].push(new Watcher(node,"innerHTML",this,attrVal));
}
if(node.hasAttribute("v-text")){// 该节点是否拥有v-text指令
let attrVal=node.getAttribute("v-text");// 获得指令对应的数据属性
this.binding[attrVal].push(new Watcher(node,"innerText",this,attrVal));
}
}
}
function Watcher(el,attr,vm,val){// 观察者
this.el=el; // 指令所在的元素
this.attr=attr;// 绑定的属性名
this.vm=vm; // 指令所在实例
this.val=val; // 指令的值
this.update(); // 更新视图view
}
Watcher.prototype.update=function(){
this.el[this.attr]=this.vm.$data[this.val];
}
三.效果图

Vue双向绑定实现原理demo的更多相关文章
- vue双向绑定的原理及实现双向绑定MVVM源码分析
vue双向绑定的原理及实现双向绑定MVVM源码分析 双向数据绑定的原理是:可以将对象的属性绑定到UI,具体的说,我们有一个对象,该对象有一个name属性,当我们给这个对象name属性赋新值的时候,新值 ...
- 最近老是有兄弟问我,Vue双向绑定的原理,以及简单的原生js写出来实现,我就来一个最简单的双向绑定,原生十行代码让你看懂原理
废话不多说直接看效果图 代码很好理解,但是在看代码之前需要知道Vue双向绑定的原理其实就是基于Object.defineProperty 实现的双向绑定 官方传送门 这里我们用官方的话来说Object ...
- vue双向绑定的原理
什么是双向数据绑定?Vue是一个MVVM框架,数据绑定简单来说,就是当数据发生变化时,相应的视图会进行更新,当视图更新时,数据也会跟着变化. 实现数据绑定的方式大致有以下几种: - 1.发布者-订阅者 ...
- vue双向绑定原理分析
当我们学习angular或者vue的时候,其双向绑定为我们开发带来了诸多便捷,今天我们就来分析一下vue双向绑定的原理. 简易vue源码地址:https://github.com/jiangzhenf ...
- Vue双向绑定原理及其实现
在之前面试的时候被面试官问到是否了解Vue双向绑定的原理,其实自己之前看过双向绑定的原理,但也就是粗略的了解,但是没有深入.面试官当时让我手写一个原理,但是就蒙了
- vue双向绑定原理源码解析
当我们学习angular或者vue的时候,其双向绑定为我们开发带来了诸多便捷,今天我们就来分析一下vue双向绑定的原理. 简易vue源码地址:https://github.com/maxlove123 ...
- 关于网上大量对Vue双向绑定的错误理解
对于Vue的双向绑定,现在基本是个前端都听说过,面试官也喜欢问这个问题.但对于Vue双向绑定的原理,掘金.博客园和segmentfault等技术社区充斥着大量的错误文章.这些文章的题目基本样子如下 “ ...
- [Vue源码]一起来学Vue双向绑定原理-数据劫持和发布订阅
有一段时间没有更新技术博文了,因为这段时间埋下头来看Vue源码了.本文我们一起通过学习双向绑定原理来分析Vue源码.预计接下来会围绕Vue源码来整理一些文章,如下. 一起来学Vue双向绑定原理-数据劫 ...
- Vue双向绑定原理,教你一步一步实现双向绑定
当今前端天下以 Angular.React.vue 三足鼎立的局面,你不选择一个阵营基本上无法立足于前端,甚至是两个或者三个阵营都要选择,大势所趋. 所以我们要时刻保持好奇心,拥抱变化,只有在不断的变 ...
随机推荐
- hsv空间
hsv在不同的软件中,有不同的阈值, 在描述阈值之前,看一下它的定义,按照标准的定义,hsv应该是从0°到360°的一个环,加上一个表示亮度的轴,重点就是那个环. 这个环如图一,0°一般为红色120° ...
- 洛谷3384&bzoj1036树链剖分
值得注意的是: 一个点的子树是存在一起的...也就是说我们修改子树的时候只用... /********************************************************* ...
- bzoj 3926: 诸神眷顾的幻想乡 广义后缀自动机
题目: Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给 ...
- python 3中使用getattr和*args时, 出现传入参数不一致的问题
今天在用python3的getattr时遇到一个问题, 就是老提示传入参数和函数前面不一致, 代码为: class Test: def __init__(self, name): ...
- 宽字符wchar_t和窄字符char区别和相互转换
转自:http://blog.csdn.net/nodeathphoenix/article/details/7416725 1. 首先,说下窄字符char了,大家都很清楚,就是8bit表示的b ...
- 【总结整理】javascript的函数调用时是否加括号
javascript的函数调用时是否加括号 if(event.preventDefault){ event.preventDefault(); if判断条件里面不要加括号,不加括号是应该以属性形式,i ...
- mongodb插入时间
插入时间: db.test.insert({time:new Date()}) 给mongodb插入日期格式的数据时发现,日期时间相差8个小时,原来存储在mongodb中的时间是标准时间UTC +0: ...
- eclipse 远程操作HIVE
首先启动HiveServer hive --service hiveserver 10000 & 创建工程 引入包: 代码(简单的查询): package com.hive.jdbc; imp ...
- ubuntu14.04装完系统更新后桌面挂了
一开始是只显示个鼠标什么都没有,ctrl-alt-1切到控制台下,把lightdm重启下再进去,多了两个桌面图标,但是顶栏和侧栏都没有,也就是根本没法运行其它程序. 但是幸好桌面右键菜单里有一个“在控 ...
- windows 下隐藏 system 函数弹窗
概述 下面的程序是解决windows 下面调用 system() 函数的时候,会有窗口弹出的问题 头文件 #include <windows.h> 源码 /** * @brief 普通字符 ...