## 数据驱动
vue执行流程
1、获得模板 模板中有坑 {{}}就是先获取到这样的一个模板
<div class="root" id="root">
<div>
<p>{{name}} {{message}}</p>
</div>
<p>{{name}}</p>
<p>{{message}}</p>
</div>
2、利用vue构造函数中的数据来进行填坑,得到可以再页面中显示的标签
vue其实就是利用我们提供的数据和页面中的模板生成了一个新的html标签,替换到页面中放置模板的的位置
现在先简单的对这个填坑的操作进行一个模拟
1、首先先写一个模板就像vue那样的标签结构
<div class="root" id="root">
<div>
<p>{{name}} {{message}}</p>
</div>
<p>{{name}}</p>
<p>{{message}}</p>
</div>
2、获取到标签结构
let template = document.querySelector('#root')
3、定义变量data
let data = {
name: "一个新name",
message: "一个消息"
}
4、使用递归对标签进行处理
//花括号的正则
var kuohao = /{{(.+?)}}/g
function compiler(template, data) {
let childrenNodes = template.childNodes; //取出子元素
console.log(childrenNodes)
for (var i = 0; i < childrenNodes.length; i++) {
let type = childrenNodes[i].nodeType; //1、 文本 3、文本节点
if (type === 3) {
//文本节点可以判断是否有{{}}插值
let txt = childrenNodes[i].nodeValue; //该属性只有文本节点才有意义
//判断有没有双括号
let txt2 = txt.replace(kuohao, function (_, g) {
//replace使用正则匹配一次就会被调用一次函数
let key = g.trim()//写在花括号里面的东西
// console.log('g', g)
let value = data[key]
//将{{xxx}}用这个进行替换
//txt与dom没有关系的
return value
})
childrenNodes[i].nodeValue = txt2
} else if (type === 1) {
//元素,考虑是否有子元素,是否需要将其进行递归处理,判断是否要插值
compiler(childrenNodes[i], data)
}
}
}
整体代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="root" id="root">
<div>
<p>{{name}} {{message}}</p>
</div>
<p>{{name}}</p>
<p>{{message}}</p>
</div>
</body>
<script>
var kuohao = /{{(.+?)}}/g
//步骤
//1、拿到模板
//2、拿到数据
//3、将数据与模板结合,得到的是html元素
//4、放与页面中
//拿到模板
let template = document.querySelector('#root')
let data = {
name: "一个新name",
message: "一个消息"
}
//使用递归
//当前案例中的template是dom元素 ,在vue源码中是dom->字符串模板->vNode => dom
function compiler(template, data) {
let childrenNodes = template.childNodes; //取出子元素
console.log(childrenNodes)
for (var i = 0; i < childrenNodes.length; i++) {
let type = childrenNodes[i].nodeType; //1、 文本 3、文本节点
if (type === 3) {
//文本节点可以判断是否有{{}}插值
let txt = childrenNodes[i].nodeValue; //该属性只有文本节点才有意义
//判断有没有双括号
let txt2 = txt.replace(kuohao, function (_, g) {
//replace使用正则匹配一次就会被调用一次函数
//函数第0个参数表示匹配到的内用
//函数的第n个参数 表示u正则中的第n组
let key = g.trim()//写在花括号里面的东西
// console.log('g', g)
let value = data[key]
//将{{xxx}}用这个进行替换
//txt与dom没有关系的
return value
})
childrenNodes[i].nodeValue = txt2
} else if (type === 1) {
//元素,考虑是否有子元素,是否需要将其进行递归处理,判断是否要插值
compiler(childrenNodes[i], data)
}
}
}
let genereateNode = template.cloneNode(true)
console.log(template)
compiler(genereateNode, data)
console.log(genereateNode)
//没有生成新的template 所以这里是直接在页面中更新数据的,因为dom是引用类
//放于页面中
root.parentNode.replaceChild(genereateNode, root)
/*
上面的思路有很大的问题
1、vue使用的是虚拟dom
2、只考虑了单属性 {{name}} , 而vue中 使用层级是 {{children.name}}
3、代码没有整合
*/
</script>
</html>
\