调用

<!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 版本)的更多相关文章

  1. vue双向绑定(数据劫持+发布者-订阅者模式)

    参考文献:https://www.cnblogs.com/libin-1/p/6893712.html 实现mvvm主要包含两个方面,数据变化更新视图,视图变化更新数据. 关键点在于data如何更新v ...

  2. vue 结合localStorage 来双向绑定数据

    结合localStorage 来双向绑定数据(超级神奇) localStorage.js: const STORAGE_KEY = 'todos_vuejs' export default { fet ...

  3. 组件的通信 :provide / inject 对象进入后,就等于不用props,然后内部对象,直接复制可以接受数组,属性不能直接复制,可以用Object.assgin覆盖对象,或者Vue的set 双向绑定数据

    组件的通信 :provide / inject 对象进入后,就等于不用props,然后内部对象,直接复制可以接受数组,属性不能直接复制,可以用Object.assgin覆盖对象,或者Vue的set 双 ...

  4. 关于简单的数据双向绑定原理,defineProperty 和Proxy演示

    双向绑定,也就是说js中的数据传到页面,页面中的内容到js,实现同步更新,简单的演示可以直接复制下放HTML代码运行. 在这个例子中,我们使用defineProperty ,Object.define ...

  5. 手写vue双向绑定数据

    来一张原理图: 实现思路: (1)绑定data 种的数据,为每个数据添加指令.通过Object,defineProperty() 来通知属性是否更改 (2) 找到每个DOM节点的指令.绑定事件.并绑定 ...

  6. vue 双向绑定 数据修改但页面没刷新

    在数据改动的代码后加 this.$forceUpdate(); 若是在某个特定方法中 则将this改为方法中设定的名称

  7. js 双向绑定数据

    let aaa = []; let bbb = [1,2,3]; let ccc = [0,9,8]; aaa = bbb; //此时aaa与bbb被绑定(aaa指向bbb的指向) ,若使用push则 ...

  8. Vue 中 双向绑定数据

    1.文本 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <titl ...

  9. 深入理解Proxy 及 使用Proxy实现vue数据双向绑定

    阅读目录 1.什么是Proxy?它的作用是? 2.get(target, propKey, receiver) 3.set(target, propKey, value, receiver) 4.ha ...

随机推荐

  1. 2020-05-21:es底层读写原理?倒排索引原理?

    福哥答案2020-05-21: es不熟悉,答案仅供参考:es写数据过程1.客户端选择一个node发送请求过去,这个node就是coordinating node(协调节点)2.coordinatin ...

  2. centos go 安装 使用

    #goland 确保能ping通百度[root@z my_project]# vi /etc/resolv.conf# Generated by NetworkManagersearch locald ...

  3. Spring配置文件中bean标签中init-method和destroy-method和用注解方式配置

    Person类: public class Person {       private int i = 0;          public Person(){           System.o ...

  4. HM16.0之帧间Merge模式——xCheckRDCostMerge2Nx2N

    参考:https://blog.csdn.net/nb_vol_1/article/details/51163625 1.源代码: /** check RD costs for a CU block ...

  5. Hadoop 2.6.1 集群安装配置教程

    集群环境: 192.168.56.10 master 192.168.56.11 slave1 192.168.56.12 slave2 下载安装包/拷贝安装包 # 存放路径: cd /usr/loc ...

  6. 轻松应对并发,Newbe.Claptrap 框架入门,第四步 —— 利用 Minion,商品下单

    接上一篇 Newbe.Claptrap 框架入门,第三步 —— 定义 Claptrap,管理商品库存 ,我们继续要了解一下如何使用 Newbe.Claptrap 框架开发业务.通过本篇阅读,您便可以开 ...

  7. PyQt5+Caffe+Opencv搭建人脸识别登录界面

    PyQt5+Caffe+Opencv搭建人脸识别登录界面(转载) 最近开始学习Qt,结合之前学习过的caffe一起搭建了一个人脸识别登录系统的程序,新手可能有理解不到位的情况,还请大家多多指教. 我的 ...

  8. Git使用感悟

    前言 分支介绍 我们现在开发的分支一般是这样的(基于上面那张图片的): master:上线用的 dev:开发用的 featature_xxx:开发用的 test:测试用的 hotfix:修复bug的 ...

  9. 27倍性能之旅 - 以大底库全库向量召回为例谈Profiling驱动的性能优化

    问题 Problem kNN(k Nearest Neighbor)定义 给定一个查询向量,按照某个选定的准则(如欧式距离),从底库中选择

  10. Vue.$set的使用场景

    有这样一个需求,用户可以增加多个输入框可以编辑:     实现的思路很简单,点击增加的时候,往一个数组里面push一条数据即可: <template> <div> <di ...