调用

<!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-06-07:mysql中varchar类型的id,where id=1,会用到索引吗?int 类型的id,where id="1",会用到索引吗?为什么?

    福哥答案2020-06-07: 答案来自群员:对于int类型id,查询的varchar 类型 ‘1’会隐式转换成 1,‘1’和 1都能正常走索引:对于varchar类型id,查询的int 类型 1不会 ...

  2. 使用 VMware Workstation Pro 让 PC 提供云桌面服务——学习笔记(一)

    最终效果: 能够通过xshell等终端设备, 远程访问虚拟机 操作步骤 1. 安装VMware 网上自行下载VMware 软件,这里不给出详细操作 2. 下载安装系统 这里使用 Centos 的lin ...

  3. 实型(浮点型):float、double

    #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include<stdlib. ...

  4. [netty4][netty-handler]netty之idle handler处理

    初始化时记录idle时间,并启动一个延时任务,延时时间为idle时间,延时任务是io.netty.handler.timeout.IdleStateHandler.AllIdleTimeoutTask ...

  5. 企业项目实战 .Net Core + Vue/Angular 分库分表日志系统 | 简单的分库分表设计

    前言 项目涉及到了一些设计模式,如果你看的不是很明白,没有关系坚持下来,写完之后去思考去品,你就会有一种突拨开云雾的感觉,所以请不要在半途感觉自己看不懂选择放弃,如果我哪里写的详细,或者需要修正请联系 ...

  6. php 正则表达式匹配(持续更新)

    正则表达式匹配网址: <?php header('Content-type:text/html;charset=utf-8'); $str = ' 百度http://www.baidu.com网 ...

  7. Java面试题(设计模式篇+Spring/Spring MVC篇)

    设计模式 88.说一下你熟悉的设计模式? 自行熟悉. 89.简单工厂和抽象工厂有什么区别? 简单理解简单工厂:对 一个对象的创建进行封装.抽象工厂:对 一组对象的创建进行封装. 比如生产 陶瓷马 和  ...

  8. 放眼SEM现状及发展历程

    http://www.wocaoseo.com/thread-187-1-1.html 由于近年来移动应用的基本普及,搜索引擎营销随之进入高速发展时代,应用层次的提升已经成为企业营销策略的一个重要组成 ...

  9. asp .net core 静态文件资源

    前言 对静态资源的简单的一个概况,在<重新整理.net core 计1400篇>系列后面会深入. 正文 我们在加入中间件是这样写的: app.UseStaticFiles(); 默认是给w ...

  10. PHP - 读取EXCEL内容 存入数据库

    <?php //设置请求头 header("Content-Type:text/html;charset=utf8"); header("Access-Contro ...