现成MVVM
菜单教程
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="message">
<p>{{ message }}</p>
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
})
</script>
</body>
</html>
视图影响数据
数据影响视图
项目构架
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="./js/mvvm.js"></script>
<script src="./js/compile.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="message">
<div>{{message}}</div>
<ul>
<li></li>
</ul>
{{message}}
</div>
<script>
let vm = new MVVM({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
})
</script>
</body>
</html>
mvvm.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="./js/mvvm.js"></script>
<script src="./js/compile.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="message">
<div>{{message}}</div>
<ul>
<li></li>
</ul>
{{message}}
</div>
<script>
let vm = new MVVM({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
})
</script>
</body>
</html>
mvvm.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="./js/mvvm.js"></script>
<script src="./js/compile.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="message">
<div>{{message}}</div>
<ul>
<li></li>
</ul>
{{message}}
</div>
<script>
let vm = new MVVM({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
})
</script>
</body>
</html>
mvvm.js
class MVVM {
constructor(options) {
this.$el = options.el;
this.$data = options.data;
if (this.$el) {
new Compile(this.$el);
}
}
}
compile把dom节点,放在内存中操作(到35分钟)
class Compile {
constructor(el, vm) {
this.el = this.isElementNode(el) ? el : document.querySelector(el);
this.vm = vm;
if (this.el) {
let fragment = this.node2frament(this.el);
this.compile(fragment);
}
}
//辅助方法
isElementNode(node) {
return node.nodeType === 1;
}
//核心方法
compile(fragment) {
let childNodes = fragment.childNodes;
console.log(childNodes)
}
node2frament(el) {
let fragment = document.createDocumentFragment();
let firstChild;
while (firstChild = el.firstChild) {
fragment.appendChild(firstChild);
}
return fragment
}
}
分类元素节点和文本节点(52分钟)
class Compile {
constructor(el, vm) {
this.el = this.isElementNode(el) ? el : document.querySelector(el);
this.vm = vm;
if (this.el) {
let fragment = this.node2frament(this.el);
this.compile(fragment);
}
}
//辅助方法
isElementNode(node) {
return node.nodeType === 1;
}
isDirective(name) {
return name.includes('v-')
}
//核心方法
compileElement(node) {
let attrs = node.attributes;
Array.from(attrs).forEach(arrt => {
let attrName = attr.name;
if (this.isDirective(attrName)) {
let expr = attr.value;
}
})
}
compileText(node) {
let text = node.textContent;
let reg = /\{\{([^}]+)\}\}/g;
if (reg.test(text)) {
}
}
compile(fragment) {
let childNodes = fragment.childNodes;
Array.from(childNodes).forEach(node => {
if (this.isElementNode(node)) {
this.compile(node)
} else {
console.log('text', node)
}
})
}
node2frament(el) {
let fragment = document.createDocumentFragment();
let firstChild;
while (firstChild = el.firstChild) {
fragment.appendChild(firstChild);
}
return fragment
}
}
元素节点
文本节点
把data中的数据,显示在视图上(到1:16分)
class Compile {
constructor(el, vm) {
this.el = this.isElementNode(el) ? el : document.querySelector(el);
this.vm = vm;
if (this.el) {
let fragment = this.node2frament(this.el);
this.compile(fragment);
this.el.appendChild(fragment)
}
}
//辅助方法
isElementNode(node) {
return node.nodeType === 1;
}
isDirective(name) {
return name.includes('v-')
}
//核心方法
compileElement(node) {
let attrs = node.attributes;
Array.from(attrs).forEach(attr => {
let attrName = attr.name;
if (this.isDirective(attrName)) {
let expr = attr.value;
let [, type] = attrName.split('-');
CompileUtil[type](node, this.vm, expr)
}
})
}
compileText(node) {
console.log(node)
let expr = node.textContent;
let reg = /\{\{([^}]+)\}\}/g;
if (reg.test(expr)) {
CompileUtil['text'](node, this.vm, expr)
}
}
compile(fragment) {
let childNodes = fragment.childNodes;
Array.from(childNodes).forEach(node => {
if (this.isElementNode(node)) {
this.compileElement(node)
this.compile(node)
} else {
this.compileText(node)
}
})
}
node2frament(el) {
let fragment = document.createDocumentFragment();
let firstChild;
while (firstChild = el.firstChild) {
fragment.appendChild(firstChild);
}
return fragment
}
}
CompileUtil = {
getVal(vm, expr) { // 获取实例上对应的数据
expr = expr.split('.'); // [message,a]
return expr.reduce((prev, next) => { // vm.$data.a
return prev[next];
}, vm.$data);
},
getTextVal(vm, expr) { // 获取编译文本后的结果
return expr.replace(/\{\{([^}]+)\}\}/g, (...arguments) => {
return this.getVal(vm, arguments[1]);
})
},
text(node, vm, expr) { //文本处理
let updateFn = this.updater['textUpdater'];
let value = this.getTextVal(vm, expr);
updateFn && updateFn(node, value)
},
model(node, vm, expr) {
let updateFn = this.updater['modelUpdater'];
updateFn && updateFn(node, this.getVal(vm, expr));
},
updater: {
textUpdater(node, value) {
node.textContent = value;
},
modelUpdater(node, value) {
node.value = value;
}
}
}
v-model类型
modelUpdater(node, value) {
node.value = value;
console.log(node)
console.log(value)
console.log(node.value)
}
最后
为了帮助大家让学习变得轻松、高效,给大家免费分享一大批资料,帮助大家在成为全栈工程师,乃至架构师的路上披荆斩棘。在这里给大家推荐一个前端全栈学习交流圈:866109386.欢迎大家进群交流讨论,学习交流,共同进步。
当真正开始学习的时候难免不知道从哪入手,导致效率低下影响继续学习的信心。
但最重要的是不知道哪些技术需要重点掌握,学习时频繁踩坑,最终浪费大量时间,所以有有效资源还是很有必要的。
最后祝福所有遇到瓶疾且不知道怎么办的前端程序员们,祝福大家在往后的工作与面试中一切顺利。
网友评论