双向绑定数据的实现(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 ...
随机推荐
- ECharts 常见的问题总结
以前也用过ECharts(不得不说,这真的是百度的良心产品),但是都是一些简单的示例.这次因为工作的需要,做了很多表格,对ECharts有了更加深刻的理解,现在来总结一下. 第一个肯定是新手经常遇到的 ...
- Mybatis-09-缓存
缓存 什么是缓存[Cache]? 存在内存中的临时数据 提高查询效率,解决高并发的性能问题 为什么使用缓存? 减少和数据库的交互次数,减少系统开销,提高系统效率 什么样的数据能使用缓存? 经常查询且不 ...
- mac 安卓生成证书(uniapp项目安卓证书申请)
mac 安卓生成证书 义务需求: 最近在开发基于uniapp框架的app,到了打包发布的阶段,来尝试打包为安卓的apk安装包.在用HBuild打包的时候需要提供安卓的数字证书(.keystore 文 ...
- JDK1.8源码学习-LinkedList
JDK1.8源码学习-LinkedList 目录 一.LinkedList简介 LinkedList是一个继承于AbstractSequentialList的双向链表,是可以在任意位置进行插入和移除操 ...
- ssh连接:Socket error Event: 32 Error: 10053.
今天在使用xshell连接刚装的linux系统的时候,发现无法建立连接,会报如下错误: Connecting to 192.168.21x.x:22...Connection established. ...
- JavaScript学习系列博客_26_JavaScript 数组的一些方法
数组的一些方法 - push() - 用来向数组的末尾添加一个或多个元素,并返回数组新的长度 - 语法:数组.push(元素1,元素2,元素N) - pop() - 用来删除数组的最后一个元素,并返回 ...
- Mybatis_day1
mybatis框架的引入: JDBC里面 对功能实现的进一步封装,可以按照以下方式操作 Student s = new Student(id,name); util.save(s); ORM: obj ...
- 构造 IPv6 报文
#!/usr/bin/python from scapy.all import * a=IPv6(nh=58, src='fe80::214:f2ff:fe07:af0', dst='ff02::1' ...
- MySQL必知必会》正则表达式
<MySQL必知必会>正则表达式 正则表达式 1.1.关键字 REGEXP 正则表达式的使用需要用到关键字 REGEXP . select prod_name from products ...
- WordCount (Python)
Github项目地址:https://github.com/w1036933220/WordCount 一.解题思路 把项目需求理清楚,画一个思维导图 考虑各部分功能所需要的大概实现思路 然后完成了计 ...