index.html
<!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 id="app">{{msg}}
<h3>{{str}}</h3>
</div>
<script src="./vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
msg: 'hello world',
str: 'hello',
},
beforeCreate() {
console.log('beforeCreate', this.$data)
},
created() {
// 需要改变 this 的指向,否则获取不到 $data
console.log('created', this.$data)
},
beforeMount() {
console.log('beforeMount', this.$el)
},
mounted() {
console.log('mounted', this.$el)
}
})
</script>
</body>
</html>
vue.js
class Vue {
constructor(options) {
if(typeof options.beforeCreate === 'function'){
options.beforeCreate.bind(this)()
}
// 数据绑定
this.$data = options.data;
if(typeof options.created === 'function'){
options.created.bind(this)();
}
if (typeof options.beforeMount === "function") {
options.beforeMount.bind(this)();
}
// 节点
this.$el = document.querySelector(options.el);
// 解析节点
this.compile(this.$el);
if(typeof options.mounted === 'function'){
options.mounted.bind(this)();
}
}
compile(node) {
if (node.childNodes && node.childNodes.length) {
node.childNodes.forEach((child) => {
// nodeType 1: 元素节点 3: 文本节点
if (child.nodeType === 3) {
// 文本节点
let reg = /\{\{(.*)\}\}/;
let text = child.textContent;
// 给节点赋值
child.textContent = text.replace(reg, (matched, value) => {
value = value.trim();
return this.$data[value];
});
} else {
// 元素节点
this.compile(child);
}
});
}
}
}