双向绑定数据的实现(new Proxy 版本)
调用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>myvue</title>
<script src="myvue.js"></script>
</head>
<body>
<div id="app">
姓名:{{name}}
<div>
年龄:{{age}}
<p>
身高:{{height}}
</p>
<p>
体重:{{weight}}
</p>
</div>
<div>
双向数据绑定:<input type="text" v-model="inputData">
{{inputData}}
</div>
</div>
<script>
let vm = new Myvue({
el: '#app',
data: {
name: 'lili',
age: 18,
height: '170cm',
weight: '65kg',
inputData: '双向数据绑定'
}
})
</script>
</body>
</html>
myvue.js 核心实现
// 基础知识点扫盲
// - 自定义事件,和调用自定义事件 new CustomEvent this.dispathEvent
// - 监听拦截数据方法 Proxy, new Proxy(data, set(target, prop, newValue){})
// - EventTarget 是一个 DOM 接口,由可以接收事件
class Myvue extends EventTarget{
constructor(option) {
super();
this.option = option
this._data = this.option.data;
this.el = document.querySelector(option.el);
this.observe(this._data); // 监听观察数据
this.complieNode(this.el) // 编译节点,渲染数据
}
observe(data) {
let _this = this;
// 每次访问、设置等 data 的时候,都会经过 proxy 代理过后的对象,便于拦截,监听等操作
this._data = new Proxy(data, {
set(target, prop, newValue){
// 监听到新值变化
// 如何通知视图修改数据?
console.log(newValue);
// 自定义事件
let event = new CustomEvent(prop, {
detail: newValue
});
_this.dispatchEvent(event);
return Reflect.set(...arguments) // 设置值
}
})
}
complieNode(el) {
let child = el.childNodes;
// 类数组转成数组
[...child].forEach(element => {
if(element.nodeType === 3) {
// console.log('文本节点')
let textContent = element.textContent;
// console.log(textContent) {{name}} {{age}}
let reg = /\{\{\s*([^\s\{\}]+)\s*\}\}/g;
if(reg.test(textContent)) {
let $1 = RegExp.$1;
// console.log($1); name age
if(this._data[$1]) {
element.textContent = textContent.replace(reg, this._data[$1]);
// 绑定自定义事件,自定义事件名就是 双向数据绑定的值 name age inputData
this.addEventListener($1, e => {
console.log(e)
element.textContent = textContent.replace(reg, e.detail);
})
}
}
} else if(element.nodeType===1){
// console.log('元素节点');
let attr = element.attributes;
if(attr.hasOwnProperty('v-model')) {
let keyName = attr['v-model'].nodeValue; // inputData
element.value = this._data[keyName];
// 绑定input 事件, 修改input内容时候,同时更新掉所有 {{inputData}} 数据, 即监听 inputData
element.addEventListener('input', e => {
this._data[keyName] = element.value ;
// this.observe(this._data);
})
}
this.complieNode(element)
}
});
}
}
双向绑定数据的实现(new Proxy 版本)的更多相关文章
- vue双向绑定(数据劫持+发布者-订阅者模式)
参考文献:https://www.cnblogs.com/libin-1/p/6893712.html 实现mvvm主要包含两个方面,数据变化更新视图,视图变化更新数据. 关键点在于data如何更新v ...
- 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 双 ...
- 关于简单的数据双向绑定原理,defineProperty 和Proxy演示
双向绑定,也就是说js中的数据传到页面,页面中的内容到js,实现同步更新,简单的演示可以直接复制下放HTML代码运行. 在这个例子中,我们使用defineProperty ,Object.define ...
- 手写vue双向绑定数据
来一张原理图: 实现思路: (1)绑定data 种的数据,为每个数据添加指令.通过Object,defineProperty() 来通知属性是否更改 (2) 找到每个DOM节点的指令.绑定事件.并绑定 ...
- vue 双向绑定 数据修改但页面没刷新
在数据改动的代码后加 this.$forceUpdate(); 若是在某个特定方法中 则将this改为方法中设定的名称
- js 双向绑定数据
let aaa = []; let bbb = [1,2,3]; let ccc = [0,9,8]; aaa = bbb; //此时aaa与bbb被绑定(aaa指向bbb的指向) ,若使用push则 ...
- Vue 中 双向绑定数据
1.文本 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <titl ...
- 深入理解Proxy 及 使用Proxy实现vue数据双向绑定
阅读目录 1.什么是Proxy?它的作用是? 2.get(target, propKey, receiver) 3.set(target, propKey, value, receiver) 4.ha ...
随机推荐
- 01 Arduino-点亮一盏LED灯
01 硬件连接 图片比较丑 特别说明:一般默认为二极管灯的压降是 2V 均值电流为15ma,所以如果接在5V的电源上面,串联接的电阻值为200欧姆左右,可做适当调整 切记不允许把LED灯直接并联在5 ...
- 【IDE】WebStorm 调整Tab缩进为2空格 -- 为遵循ESLint语法规范
步骤一 修改这三处的值为:2 步骤二 把这两处默认的勾选去掉,不让其detection当前文件的Tab缩进 注意! 通过上面两个步骤,我们只是改变了在JS文件的Tab缩进改为2个空格 但是,*.vue ...
- Android 找不到所标识的资源 java.lang.NoSuchFieldError: No static field XXX of type I in class Lcom/XX/R$id
报错: java.lang.NoSuchFieldError: No static field XXX of type I in class Lcom/XXX/R$id; or its supercl ...
- python 02 if while
1. if的格式 >>> 1<3 True 真>>> 1>3False 假 if 条件: 条件 + : (t ...
- 笔记:Linux用户管理(补充)、权限管理、内存管理、网络管理、渗透常用命令
一.用户管理(补充) 添加用户:useradd [选项] 用户名 useradd -u 5000 -g demogroup -G root -d /home/demo -s /bin/bash dem ...
- 5 个 Git 工作流,改善你的开发流程
原文地址:5 Git workflows you can use to deliver better code and improve your development process 原文作者:Vi ...
- php实现视频拍照上传头像功能实例代码
如果要在php中实现视频拍照我们需要借助于flash插件了,由flash拍出的确照片我们再通过php的$GLOBALS ['HTTP_RAW_POST_DATA']接受数据,然后保存成图片就可以了,下 ...
- Shell编程—创建函数
1基本的脚本函数 函数是一个脚本代码块,你可以为其命名并在代码中任何位置重用.要在脚本中使用该代码块时,只要使用所起的函数名就行了. 1.1创建函数 有两种格式可以用来在bash shell脚本中创建 ...
- 区块链入门到实战(21)之以太坊(Ethereum) – 分布式应用(DApp)
作用:用户交互 分布式应用(DApp)是运行在区块链之上的应用程序,支持区块链网络中用户之间的交互. DApp(decentralized application)的后端代码运行在区块链网络上,这个可 ...
- 学生成绩管理系统(SSM+MySQL+JSP)
开发工具:Eclipse前端技术:基础:html+css+JavaScript框架:JQuery+H-ui后端技术:Spring+SpringMVC+mybatis模板引擎:JSP数据库:mysql ...