html代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
{{ clickHere }}
<h1>{{ str }}</h1>
<h2 @click="func1">{{ clickHere }}</h2>
<input v-model="str" type="text">
</div>
<script src="../js/myVue.js"></script>
<script>
let myVue = new Vue({
el: "#app",
data: {
str: "你好234",
clickHere: "点击这里",
},
methods: {
func1(e) {
this.clickHere = "点击这里aaa"
console.log(this.clickHere);
console.log(this);
console.log(e);
}
}
})
</script>
</body>
</html>
--------------------------------------------------------
js代码:
class Vue {
constructor(options) {
this.options = options;
this.$el = document.querySelector(options.el);
this.$data = options.data;
this.$methods = options.methods;
this.$watchEvent = {};
this.proxyData();
this.compile(this.$el);
}
proxyData() {
let that = this;
for (let key in that.$data) {
// 劫持 Vue(this) 的属性
Object.defineProperty(
that,
key,
{
get: function () {
console.log("获取 data." + key + "的值: ", that.$data[key])
return that.$data[key];
},
set: function (val) {
that.$data[key] = val;
if (that.$watchEvent[key]) {
that.$watchEvent[key].forEach((item, index) => {
item.update()
})
}
}
}
)
}
}
compile(node) {
let that = this;
node.childNodes.forEach((item, index) => {
// nodeType == 1 => node 节点, 带标签
if (item.nodeType == 1) {
// 递归节点-----------------------------------------------------------
if (item.childNodes.length > 0) {
// 数据绑定
this.compile(item);
}
// @click 方法绑定-----------------------------------------------------------
if (item.hasAttribute("@click")) {
// 获取方法名
let funName = item.getAttribute("@click").trim();
item.addEventListener('click', function (event) {
// 执行该方法名对应的方法 .call() 改变this指向为Vue 对象
that.$methods[funName].call(that, event);
console.log("compile : ", that);
})
}
// v-model 绑定-----------------------------------------------------------
if (item.hasAttribute("v-model")) {
// 获取方法名
let funName = item.getAttribute("v-model").trim();
// 将数据绑定到视图
item.value = that[funName];
item.addEventListener('input', function (event) {
// 监听视图数据绑定到 model
that[funName] = item.value;
})
}
//-----------------------------------------------------------
}
// nodeType == 3 => 文本节点 不包含标签
if (item.nodeType == 3) {
let reg = /\{\{(.*?)\}\}/g;
let text = item.textContent;
item.textContent = text.replace(reg, function (match, vmKey) {
/*
function 参数 : 第一个是 匹配的全部字符
第二个是 第一个元组
第三个是 第二个元组
...
*/
vmKey = vmKey.trim();
if (that[vmKey]) {
console.log(that[vmKey]);
let watcher = new Watch(that, vmKey, item, "textContent")
if (that.$watchEvent[vmKey]) {
that.$watchEvent[vmKey].push(watcher)
} else {
that.$watchEvent[vmKey] = [];
that.$watchEvent[vmKey].push(watcher)
}
}
return that.$data[vmKey];
})
}
});
}
}
// 用来动态更新视图
class Watch {
constructor(vm, key, node, attr) {
this.vm = vm;
this.key = key;
this.node = node;
this.attr = attr;
}
update() {
this.node[this.attr] = this.vm[this.key];
}
}
vue 的 v-model 双向绑定 简单实现
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
推荐阅读更多精彩内容
- 本文能帮你做什么? 1、了解vue的双向数据绑定原理以及核心代码模块 2、缓解好奇心的同时了解如何实现双向绑定 为...
- Object.defineProperty() 实现之前我们得先看一下Object.defineProperty的...