vue ---双向数据绑定
1.后动实现v-model的双向数据绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<div class="app">
<input type="text" v-model="inputValue">
{{inputValue}}
</div>
</div>
<script>
function observe(data) {
if (!data && typeof data !== 'object'){
return;
}
Object.keys(data).forEach(key => {
defineReactive(data, key, data[key]);
})
}
function defineReactive(data, key, value) {
observe(value);
var dep = new Dep();
Object.defineProperty(data, key, {
get: function(){
console.log(222)
if(Dep.target){
dep.addSub(Dep.target)
}
return value;
},
set: function(newVal){
if(value == newVal){
return;
}
value = newVal;
dep.notify();
}
})
}
function Dep(){
this.subs = [];
}
Dep.prototype = {
addSub(sub){
this.subs.push(sub);
},
notify(){
this.subs.forEach(sub =>{
console.log(sub)
sub.update();
})
}
}
//订阅器实现
function Watcher(node, vm ,name){
Dep.target = this;
this.vm = vm;
this.node = node;
this.name = name;
this.update();
Dep.target = null;
}
Watcher.prototype = {
update(){
this.get();
if(this.node.nodeType === 3){
this.node.nodeValue = this.value;
}else{
this.node.value = this.value;
}
},
get(){
this.value = this.vm.$data[this.name];//添加订阅器
}
}
var vm1 = new Vue({
el: ".app",
data: {
inputValue: 40
}
})
function Vue(options){
this.$data = options.data;
observe(options.data);
var originDom = document.querySelector(options.el);
//需要进行编译,解析指令
var fragment = nodeToFragment(originDom, this);
document.querySelector(options.el).appendChild(fragment);
}
function nodeToFragment(node, vm){
var frameEle = document.createDocumentFragment();
var child;
while(child = node.childNodes[0]){
compile(child, vm);
frameEle.append(child);
}
return frameEle;
}
function compile(node, vm){
if (node.nodeType === 1) { //元素节点
for(var i=0; i < node.attributes.length; i++) {
if(node.attributes[i].nodeName === 'v-model'){
var name = node.attributes[i].nodeValue;
node.value = vm.$data[name];
node.addEventListener('input', function(e){
vm.$data[name] = e.target.value;
})
node.removeAttribute('v-model');
}
}
new Watcher(node, vm, name);
}
if(node.nodeType === 3){
let reg = /\{\{(.*)\}\}/; // {{xxx}}
if(reg.test(node.nodeValue)){
//console.log(node.nodeValue,RegExp.$1)
var name = RegExp.$1;
node.nodeValue = vm.$data[name];
}
new Watcher(node, vm, name);
}
}
setTimeout(()=>{
vm1.$data.inputValue = 80;
},2000)
</script>
</body>
</html>

浙公网安备 33010602011771号