本文主要包含vue.js双向数据绑定实现原理,vue.js双向绑定,vue.js双向绑定原理,vue.js双向数据绑定等相关知识,初漾希望在学习及工作中可以帮助到您
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="text" v-model="text">
{{text}}
</div>
<script>
/*var dom = nodeToFragment(document.getElementById('app'));
console.log(dom);*/
function compile(node,vm) {
var reg =/\{\{(.*)\}\}/;
//节点类型为元素
if(node.nodeType === 1){
var attr = node.attributes;
//解析属性
for(var i=0;i<attr.length;i++){
if(attr[i].nodeName = 'v-model'){
var name = attr[i].nodeValue;//获取v-model绑定的属性名
//放在该位置原因是获取name值
node.addEventListener('input',function (e) {
//给相应的data属性赋值,进而触发该属性的set方法
vm[name]=e.target.value;
});
node.value = vm[name];
node.removeAttribute('v-model');
}
};
}
//节点类型为text
if(node.nodeType === 3){
if(reg.test(node.nodeValue)){
var name = RegExp.$1;//1.获取匹配到的字符串
name = name.trim();
//node.nodeValue = vm[name];//将data的值赋值给该node
new Watcher(vm,node,name);
}
}
}
function nodeToFragment(node,vm) {
var flag = document.createDocumentFragment();
var child;
while(child = node.firstChild){
compile(child,vm);
flag.append(child);
}
return flag;
}
function defineReactive(obj,key,val) {
var dep = new Dep();
Object.defineProperty(obj,key,{
get:function () {
if(Dep.target) dep.addSub(Dep.target);
return val;
},
set:function (newVal) {
if(newVal===val) return ;
val = newVal;
//console.log(val);
//作为发布者发出通知
dep.notify();
}
});
}
function observe(obj,vm) {
Object.keys(obj).forEach(function (key) {
defineReactive(vm,key,obj[key]);
})
}
function Vue(options) {
this.data = options.data;
var data = this.data;
observe(data,this);
var id = options.el;
var dom = nodeToFragment(document.getElementById(id),this);
//编译完成后,将dom返回到app中
document.getElementById('app').appendChild(dom);
}
function Dep() {
this.subs = [];
}
Dep.prototype={
addSub:function (sub) {
this.subs.push(sub);
},
notify:function () {
this.subs.forEach(function (sub) {
sub.update();
});
}
}
function Watcher(vm,node,name) {
Dep.target = this;
this.name = name;
this.node = node;
this.vm = vm;
this.update();
Dep.target=null;
}
Watcher.prototype={
update:function () {
this.get();
this.node.nodeValue = this.value;
},
//获取data中的属性值
get:function () {
this.value = this.vm[this.name];//触发相应属性的get
}
};
var vm = new Vue({
el:'app',
data:{
text:'hello world'
}
});
</script>
</body>
</html>