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 三足鼎立的局面,你不选择一个阵营基本上无法立足于前端,甚至是两个或者三个阵营都要选择,大势所趋. 所以我们要时刻保持好奇心,拥抱变化,只有在不断的变 ...
随机推荐
- 使用命令行生成 APNG 图片
使用 apngasm 工具 下载地址 https://sourceforge.net/projects/apngasm/files/2.91/ 本地源码编译 make 或者 下载对应环境的可执行程序 ...
- leetcode 258. Add Digits(数论)
Given a non-negative integer num, repeatedly add all its digits until the result has only one digit. ...
- leetcode 34 Search for a Range(二分法)
Search for a Range Given a sorted array of integers, find the starting and ending position of a give ...
- windows 安装 pytorch
之前都在服务器上跑pytorch,近来发现新版本可在windows上跑了,甚是开心. 环境: windows7 python3 无CPU 步骤: 1. 确保确保python版本在3.5.3/3.6. ...
- linux命令学习笔记(3):pwd命令
Linux中用 pwd 命令来查看”当前工作目录“的完整路径. 简单得说,每当你在终端进行操作时, 你都会有一个当前工作目录. 在不太确定当前位置时,就会使用pwd来判定当前目录在文件系统内的确切位置 ...
- C语言小程序(二)、计算第二天日期
输入一个日期,判断下一个日期是哪一天,如果日期输入错误,则调用Linux下的cal命令显示输入的月份. #include <stdio.h> #include <stdlib.h&g ...
- 【JSON解析】JSON解析
前三篇博客分别介绍了xml的三种解析方法,分别是SAX,DOM,PULL解析XML,兴趣的朋友可以去看一下这[XML解析(一)]SAX解析XML,[XML解析(二)]DOM解析XML,[XML解析(三 ...
- [转]unity3d中创建双面材质
在其它三维软件中设置好的双面材质导入到unity3d中就失去了效果,不过我们可以通过自定义材质来在unity3d中实现双面材质的效果.步骤如下:1.在资源库中新建一新shader:代码如下: Shad ...
- Oracle---SQL子查询---详解
子查询其实就是指嵌入到其他语句中的select语句,也称其为嵌套查询. 值得注意的在DDL语句中应用子查询的时候子查询可以使用order by 子句. 但是在DML语句中的where子句,set子句中 ...
- Ajax调用后台方法报未定义
需要在web.config中<system.webServer>节点下添加如下内容 <handlers> <add name="ajax" verb= ...