function Dep() {
this.subs = {}; // 仓库
}
Dep.prototype.addSub = function (sub, name) {
// sub = 对应的span {{}}
this.subs[name] = sub;
};
Dep.prototype.notify = function (name) {
// sub = 对应的span {{}}
this.subs[name].update();
};
function Watcher(vm, node, name) {
// 把内容通过this的方式保存起来 , 添加到Dep仓库里
// 这里相当于定义了一个对象 把对象保存到dep仓库里
Dep.target = this;
this.name = name;
this.vm = vm;
this.node = node;
this.update();
Dep.target = null;
}
Watcher.prototype.update = function () {
this.node.innerHTML = this.vm[this.name]
};
/*var Dep = (function () {
var subs = {};
return {
addSub: function (value) {
subs = value
}
}
}());*/
function compile(node, vm) {
var reg = /\{\{(.*)\}\}/;
var name;
if (node.nodeType === 1) {
if (node.hasAttribute("v-model")) {
name = node.getAttribute("v-model");
node.addEventListener("input", function (e) {
vm[name] = e.target.value;
});
// 文本框默认的value = 实例化对象身上对应的set get的数据
node.value = vm[name];
node.removeAttribute("v-model");
} else if (reg.test(node.innerText)) {
name = RegExp.$1;
name = name.trim();// 清楚左右的空格
node.innerText = vm[name]; // 把{{}}所在的元素节点内容改变成对应的数据
new Watcher(vm, node, name);// 把元素保存起来方便以后使用
}
}
}
// 处理(整理)原始dom
function nodeToFragment(node, vm) {
// 创建代码片段
var flag = document.createDocumentFragment();
var child;
while (child = node.firstChild) {
// 整理dom 把v-model 之类的东西处理之后
// ......
compile(child, vm);
flag.appendChild(child);
}
return flag;
}
function defineReactive(vm, key, value) {
var dep = new Dep();
Object.defineProperty(vm, key, {
get: function () {
Dep.target && dep.addSub(Dep.target, key);
return value;
},
set: function (newVlaue) {
value = newVlaue;
// 让{{}}更新
dep.notify(key);
}
})
}
function observe(data, vm) {
for (var key in data) {
defineReactive(vm, key, data[key]);
}
}
function Wulv(options) {
this.data = options.data;
observe(this.data, this);
var el = document.getElementById(options.el);
var dom = nodeToFragment(el, this);
el.appendChild(dom);
}
var app = new Wulv({
el: "app",// 范围
data: {
name: "name",
age: 18,
goudan: "goudan"
}
});
// 1.把接收到 的数据进行get set
// 2.处理dom 把v-model {{}}
// 3.同时把{{}}所在的节点保存起来
// 触发set(input事件触发的时候)
// 让原有的值 = 新的值(刚刚在input里输入的内容)
// 让对应的{{}}所在的节点的内容更新
/*new Vue({
el: "#app",
data: {
name: "wulv",
age: 18
}
})*/
/*var obj = {};
function goudan() {
this.goudan = "goudan";
obj.target = this;
// this 指向的实例化对象
}
// var a = new goudan();
// a 实例化对象
console.log(a === obj.target);*/