1、view视图层
实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
2、mode数据层
实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,
执行指令绑定的相应回调函数,从而更新视图
具体代码实现原理
/**
* 初始化vue对象,把定义的组件的vue对象初始
* 获取lue对象的data数据,实行data属性的数据双向绑定
*
*/
class Lue {
constructor(options) {
// 参数私有化
this.data = options.data
var data = this.data
var id = options.el
// 1、对数据模型的监听,对数据层的管理
observe(data, this)
// 2、对视图层的监听,实现视图层的同步
var dom = nodeToFragment(document.getElementById(id), this)
document.getElementById(id).appendChild(dom)
}
}
//mode
function observe(obj, vm) {
// 这里特别注意,我们以前直接返回data为json格式对象,现在为函数对象
// 取出所有属性遍历
let dataJson=""
if (!obj || typeof obj !== 'function') {
dataJson = obj
}else{
dataJson = obj.apply()
}
Object.keys(dataJson).forEach((objkey) => {
defineRecActive(vm, objkey, dataJson[objkey])
})
}
// 数据热反应堆
function defineRecActive(vm, key, value) {
// observe(value,vm); // 监听子属性
var dep = new Dep()
Object.defineProperty(vm, key, {
set: function (val) {
if (val === value) {
retutn
}
value = val
dep.notiy()
},
get: function () {
if (Dep.target) {
dep.addSubs(Dep.target)
}
return value;
}
})
}
class Watcher {
constructor(vm, node, name) {
Dep.target = this;
this.vm = vm;
this.node = node;
this.name = name;
this.update();
Dep.target = null;
}
update() {
this.get()
this.node.nodeValue = this.value
}
get() {
this.value = this.vm[this.name]
}
}
class Dep {
constructor() {
this.subs = [] // 创建wahcher仓库
}
addSubs(sub) {
this.subs.push(sub)
}
notiy() {
this.subs.forEach((sub) => {
sub.update()
})
}
}
// dom 模版引擎整理-------------------------------视图层整理---------------------------------------
function nodeToFragment(node, vm) {
//整理现有最新的dom对象
var flag = document.createDocumentFragment(); //这个是创建一个文档片段
var child;
// 把node的信息全部移动到flag中
while (child = node.firstChild) {
Compile(child, vm)
flag.append(child)
}
return flag
}
function Compile(node, vm) {
// 我们对标签节点进行过滤
if (node.nodeType === 1) {
if (node.hasAttribute("v-model")) {
var name = node.getAttribute("v-model");
console.log("name: " + name)
node.addEventListener('input', e => {
vm[name] = e.target.value
console.log(vm)
})
}
node.value = vm[name]
node.removeAttribute("v-model")
}
let reg = /\{\{(.*)\}\}/
if (node.nodeType === 3) {
if (reg.test(node.nodeValue)) {
var name = RegExp.$1
name = name.trim()
console.log(name)
node.nodeValue = vm[name]
}
}
new Watcher(vm, node, name) // 进行➡监听
}
// dom 模版引擎整理-------------------------------视图层整理---------------------------------------