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 三足鼎立的局面,你不选择一个阵营基本上无法立足于前端,甚至是两个或者三个阵营都要选择,大势所趋. 所以我们要时刻保持好奇心,拥抱变化,只有在不断的变 ...
随机推荐
- 热门游戏 2048 C++ 源代码分享
/*By Reason*/ #include<iostream> #include <iomanip> #include<math.h> #include<s ...
- dubbo monitor simple 监控原理分析
监控机制: 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心.监控中心负责统计各服务调用次数,调用时间等. 监控元数据存储目录结构: --dubbo.jetty ...
- C#实现根据传入时间段,找出时间段内日期,并生成相对应文件路径
[1]获取固定日期范围内的所有日期,以数组形式返回 /// <summary> /// 获取固定日期范围内的所有日期,以数组形式返回 /// </summ ...
- CF510E. Fox And Dinner
CF510E. Fox And Dinner https://codeforces.com/contest/510 分析: 由于\(a_i>2\), 相邻两个数一定一奇一偶,按奇偶建立二分图. ...
- 霍夫变换Hough
http://blog.csdn.net/sudohello/article/details/51335237 霍夫变换Hough 霍夫变换(Hough)是一个非常重要的检测间断点边界形状的方法.它通 ...
- iOS项目添加PCH文件
1.单击Info.plist右键单击->New File->Other->PCH File创建PCH文件 文件名设置成:项目名-Prefix ->点击Create,创建成功. ...
- [转]前端网络(性能)监测工具berserkJS
berserkJS 是基于 Qt (C++跨平台库)开发的前端网络(性能)监测工具. 它的核心功能是通过内置 webkit 收集由页面实际网络请求相关数据. 偏重于页面上线前检测与评估. 页面性能分析 ...
- Parallel Programming-Task Result && Continuation Task
本文主要介绍带有返回值的Task和Continuation Task 带返回值的Task Continuation Task ContinueWhenAll即多任务延续 一.带返回值的Task 1.1 ...
- BZOJ1113:[POI2008]PLA
浅谈栈:https://www.cnblogs.com/AKMer/p/10278222.html 题目传送门:https://lydsy.com/JudgeOnline/problem.php?id ...
- 清理:db上面的过期的binlog,释放磁盘空间。 (转)
如果10台以内的db的话,自己手动ssh进去,clean就足以,但是上百台呢,就要写脚本了.大概思路:在 一台db跳转机上面, 写一个脚本,访问slave,远程获取正在复制的master上面的binl ...