手写vue双向绑定数据
来一张原理图:
实现思路:
(1)绑定data 种的数据,为每个数据添加指令。通过Object,defineProperty() 来通知属性是否更改
(2) 找到每个DOM节点的指令。绑定事件。并绑定watcher
(3) 实现DOM事件改变之后, 响应data数据,实现视图更新
<!DocType>
<html>
<title>vue 的双向绑定事件</title>
<body id="app">
<input type="text" v-model="number"/>
<span v-bind="number"></span>
<input type="text" v-model="age"/>
<span v-bind="age"></span>
</body> <script>
function Vue (options) {
this._init(options);
} Vue.prototype._init = function (options) {
this.$data = options.data;
this.$methods = options.data.methods;
this.$el = document.querySelector(options.el);
this.$methods = options.methods;
this.$key = ''; this._binding = {}; // 观测数据
this._observer(this.$data); this._complie(this.$el); // this._test(this.$data);
} // 观测数据
Vue.prototype._observer = function (obj) {
var value;
let _this = this;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
this._binding[key] = {
_directives: []
};
value = obj[key];
if (typeof value === 'object') {
this._observer(value);
}
Object.defineProperty(this.$data, key, {
enumerable: true,
configurable: true,
get: function () {
console.log(`获取${value}`, key);
return value;
},
set: function (newVal) {
console.log('key:', key, _this.$key);
if (value !== newVal) {
value = newVal;
_this._binding[_this.$key]._directives.forEach(function (item, index) {
item.update();
})
}
}
})
}
}
} // 为DOM节点添加指令事件
Vue.prototype._complie = function (root) {
var _this = this;
var nodes = root.children;
for (var i = ; i < nodes.length; i++) {
var node = nodes[i];
if (node.children.length) {
this._complie(node);
} if (node.hasAttribute('v-click')) {
node.onclick = (function () {
var attrVal = nodes[i].getAttribute('v-click');
return _this.$methods[attrVal].bind(_this.$data);
})();
} if (node.hasAttribute('v-model') && (node.tagName == 'INPUT' || node.tagName == 'TEXTAREA')) {
node.addEventListener('input', (function(key) {
var attrVal = node.getAttribute('v-model');
_this._binding[attrVal]._directives.push(new Watcher(
'input',
node,
_this,
attrVal,
'value'
)) return function() {
_this.$key = attrVal
_this.$data[attrVal] = nodes[key].value;
}
})(i));
} if (node.hasAttribute('v-bind')) {
var attrVal = node.getAttribute('v-bind');
_this._binding[attrVal]._directives.push(new Watcher(
'text',
node,
_this,
attrVal,
'innerHTML'
))
}
}
} function Watcher(name, el, vm, exp, attr) {
this.name = name; //指令名称,例如文本节点,该值设为"text"
this.el = el; //指令对应的DOM元素
this.vm = vm; //指令所属myVue实例
this.exp = exp; //指令对应的值,本例如"number"
this.attr = attr; //绑定的属性值,本例为"innerHTML" this.update();
} // 更新数据
Watcher.prototype.update = function () {
this.el[this.attr] = this.vm.$data[this.exp];
} // 测试
Vue.prototype._test = function($data) {
var a = $data.number;
$data.number = ;
} window.onload = function () {
var app = new Vue({
el: '#app',
data: {
number: ,
age:
},
methods: {}
})
} </script>
</html>
手写vue双向绑定数据的更多相关文章
- vue双向绑定(数据劫持+发布者-订阅者模式)
参考文献:https://www.cnblogs.com/libin-1/p/6893712.html 实现mvvm主要包含两个方面,数据变化更新视图,视图变化更新数据. 关键点在于data如何更新v ...
- vue 双向绑定 数据修改但页面没刷新
在数据改动的代码后加 this.$forceUpdate(); 若是在某个特定方法中 则将this改为方法中设定的名称
- 用ES6的class模仿Vue写一个双向绑定
原文地址:用ES6的class模仿Vue写一个双向绑定 点击在线尝试一下 最终效果如下: 构造器(constructor) 构造一个TinyVue对象,包含基本的el,data,methods cla ...
- vue 结合localStorage 来双向绑定数据
结合localStorage 来双向绑定数据(超级神奇) localStorage.js: const STORAGE_KEY = 'todos_vuejs' export default { fet ...
- 组件的通信 :provide / inject 对象进入后,就等于不用props,然后内部对象,直接复制可以接受数组,属性不能直接复制,可以用Object.assgin覆盖对象,或者Vue的set 双向绑定数据
组件的通信 :provide / inject 对象进入后,就等于不用props,然后内部对象,直接复制可以接受数组,属性不能直接复制,可以用Object.assgin覆盖对象,或者Vue的set 双 ...
- [Vue源码]一起来学Vue双向绑定原理-数据劫持和发布订阅
有一段时间没有更新技术博文了,因为这段时间埋下头来看Vue源码了.本文我们一起通过学习双向绑定原理来分析Vue源码.预计接下来会围绕Vue源码来整理一些文章,如下. 一起来学Vue双向绑定原理-数据劫 ...
- 最近老是有兄弟问我,Vue双向绑定的原理,以及简单的原生js写出来实现,我就来一个最简单的双向绑定,原生十行代码让你看懂原理
废话不多说直接看效果图 代码很好理解,但是在看代码之前需要知道Vue双向绑定的原理其实就是基于Object.defineProperty 实现的双向绑定 官方传送门 这里我们用官方的话来说Object ...
- 剖析手写Vue,你也可以手写一个MVVM框架
剖析手写Vue,你也可以手写一个MVVM框架# 邮箱:563995050@qq.com github: https://github.com/xiaoqiuxiong 作者:肖秋雄(eddy) 温馨提 ...
- 手写 Vue 系列 之 Vue1.x
前言 前面我们用 12 篇文章详细讲解了 Vue2 的框架源码.接下来我们就开始手写 Vue 系列,写一个自己的 Vue 框架,用最简单的代码实现 Vue 的核心功能,进一步理解 Vue 核心原理. ...
随机推荐
- [转]MFC下关于“建立空文档失败”问题的分析
这类问题的出现主要在bool CWinApp::ProcessShellCommand(CCommandLineInfo& rCmdInfo); 函数的关键内容: BOOL bResult = ...
- Blog Contents
This page is intently left for contents catalog of my articles. |----------------------------------- ...
- spring amqp初步了解
Rabbitmq简介 生产者会把消息发送给RabbitMQ的交换中心(Exchange),Exchange的一侧是生产者,另一侧则是一个或多个队列,由Exchange决定一条消息的生命周期--发送给某 ...
- Python中 __init__的通俗解释?附修饰器contextmanager的理解
作者:匿名用户链接:https://www.zhihu.com/question/46973549/answer/103805810来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...
- office2016word 每次打开都有进度条问题 解决方式
最佳答案 每次打开Office 2016都提示配置进度(包括Word.PPT.Excel等等Office产品都有这种现象),如图,先是显示“安装程序正在准备必要的文件”,接着显示“正在配置Mi ...
- jquery訪问ashx文件演示样例
.ashx 文件用于写web handler的..ashx文件与.aspx文件类似,能够通过它来调用HttpHandler类,它免去了普通.aspx页面的控件解析以及页面处理的过程.事实上就是带HTM ...
- 【H5】直接拨打电话
一般<a href="tel:400-663-5999">400-663-5999</a>实现. 而形如<a href="tel:*9204 ...
- Landen邀请码
Y2PZ6U8 landen 输入邀请码,注册一年会额外赠送一个月,注册两年会额外赠送三个月.
- 20155202《网络对抗》Exp8 Web基础
20155202<网络对抗>Exp8 Web基础 基础问题回答 什么是表单? 表单是一个包含表单元素的区域,表单元素是允许用户在表单中(比如:文本域.下拉列表.单选框.复选框等等)输入信息 ...
- 20155204《网络对抗》Exp 6 信息搜集与漏洞扫描
20155204<网络对抗>Exp 6 信息搜集与漏洞扫描 一.实验后回答问题 1.哪些组织负责DNS,IP的管理. 互联网名称与数字地址分配机构,简称ICANN机构,决定了域名和IP地址 ...