vue源码之数据渲染为视图
前言:vue是如何将从后台获取的数据显示到我们的页面中的呢,其实他是使用了mustache引擎,这东西其实就是将数据变为视图的一种解决方式,那么为啥要用这种解决方式呢?其实在数据转视图的发展史中,有过很多的解决方法,但是mustache引擎是最为优雅的一种方式,下面让我们来分别列举并对比各种数据转视图的方式。
数据转视图的几种方式
1.原生DOM -- 贼麻烦
<!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>
<ul id="list"></ul>
<script>
var list = [{ name: "wsj" }, { name: "ddd" }, { name: "study" }]
var ulList = document.getElementById("list")
for (var i = 0; i < list.length; i++) {
// 每次遍历数组的其中一项,都要使用dom方法去创建li标签
let oLi = document.createElement("li")
oLi.innerText = list[i].name
// 将创建的节点插入到UL中
ulList.appendChild(oLi)
}
</script>
</body>
</html>
一顿操作猛如虎,结果渲染个二百五,这种方法需要不停的创建和插入dom,灰常不人性化
2.数组join法-- 其实就是在DOM的基础上升个级
<!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>
<ul id="list"></ul>
<script>
var list = [{ name: "wsj" }, { name: "ddd" }, { name: "study" }]
var uLi = document.getElementById("list")
for (var i = 0; i < list.length; i++) {
// 遍历数组,每次遍历,以字符串的形式将html字符串添加到list中
uLi.innerHTML += [
"<li>",
'<div class ="hd"></div>',
'<div class ="bd">',
"<p>姓名:" + list[i].name + "</p>",
"</div>",
"</li>",
].join("")
}
</script>
</body>
</html>
他的原理就是利用数组的join方法将数组转换成html格式的字符串,然后将字符串插入到DOM的innerHTML中,比原生DOM削微效率高点!
3.反引号法 -- ES6语法代替数组join法
<!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>
<ul id="list"></ul>
<script>
var list = [{ name: "wsj" }, { name: "ddd" }, { name: "study" }]
var uLi = document.getElementById("list")
for (var i = 0; i < list.length; i++) {
// 遍历数组,每次遍历,以字符串的形式将html字符串添加到list中
uLi.innerHTML += ` <li>
<div class ="hd"></div>
<div class ="bd">
<p>姓名:${list[i].name}</p>
</div>
</li>`
}
</script>
</body>
</html>
其实就是将数组的join法做了一个优化替换,得到的结果和join法一模一样
4.Mustache方法
Mustache(胡子)模板其实就是我们在vue中常见的双大括号展示数据的方法,工作原理是利用形似胡子的双大括号将数据循环至DOM字符串中,并生成一个新的DOM字符串,然后我们再将这个新的DOM字符串添加至DOM元素中的innerHTML中实现数据渲染,主要使用其暴漏的Mustache.render方法实现。下面我们介绍一下Mustache的基本使用方法和render方法。
数据循环
①.首先将Mustache.js导入到我们本地,下面是文件地址
②.引入Mustache.js文件到我们的script标签中
<script src="./mustache.js"></script>
③.创建一个DOM字符串
## 首先创建一个dom字符串,其中{{#arr}}{{/arr}}是mustache中的循环语法,你可以将其理解成为vue中的v-for
var domStr = `
<ul>
{{#arr}}
<li>
<div class='hd'>Mustache模板</div>
<div class='bd'>
<p>{{name}}</p>
</div>
</li>
{{/arr}}
</ul>
`
④.新建一个对象存放需要遍历的数据
var data = {
arr: [{ name: "wsj" }, { name: "ddd" }, { name: "study" }],
}
⑤.使用render方法将domStr转换成我们需要的DOM字符串
*render方法有两个参数,第一个是需要转换的字符串,也就是我们上面有mustache双大括号的字符串,第二个参数就是存放数据的对象,注意对象中的属性名必须是我们mustache循环语法中所用到的名称*
const listStr = mustache.render(domStr, data)
## 我们将其打印出来
console.log(listStr)
可以看到我们打印出的数据跟我们使用上面三种方法生成的DOM字符串一样 ⑥.将DOM字符串添加至dom的innerHTML中
var list = document.getElementById("list")
list.innerHTML = listStr
最终在浏览器中的结果:
简单数据循环
mustache也可以进行简单数据循环,上述的数据arr数组里面是对象,如果其中是字符串的话,我们可以用{{.}}进行渲染
var domStr = `
<ul>
{{#arr}}
<li>
<div class='hd'>Mustache模板</div>
<div class='bd'>
<p>{{.}}</p>
</div>
</li>
{{/arr}}
</ul>
`
// 2.创建一个对象,存放需要遍历的数据
var data = {
arr: ["wsj", "ddd", "study "],
}
数组的嵌套
mustache相比其他方法,其优势不仅仅在于代码的优雅展示,更在于对嵌套数组的处理,数组中嵌套数组,我们直接在双大括号中添加嵌套的数组名即可
var domStr = `
<ul>
{{#arr}}
<li>
{{name}}的爱好:
<ol>{{hobbies}}</ol>
</li>
{{/arr}}
</ul>
`
// 2.创建一个对象,存放需要遍历的数据
var data = {
arr: [
{ name: "wsj", hobbies: ["吃饭", "睡觉", "打豆豆"] },
{ name: "ddd", hobbies: ["跑步", "游泳", "骑行"] },
{ name: "study", hobbies: ["打游戏"] },
],
}
结果展示:
代码优化:
var domStr = `
<ul>
{{#arr}}
<li>
{{name}}的爱好:
<ol>
{{#hobbies}}
<li>{{.}}</li>
{{/hobbies}}
</ol>
</li>
{{/arr}}
</ul>
`
// 2.创建一个对象,存放需要遍历的数据
var data = {
arr: [
{ name: "wsj", hobbies: ["吃饭", "睡觉", "打豆豆"] },
{ name: "ddd", hobbies: ["跑步", "游泳", "骑行"] },
{ name: "study", hobbies: ["打游戏"] },
],
}
布尔值的应用
如果数据对象中存在一个布尔值,我们可以利用其控制数据的显示与隐藏,你可以将其理解为vue的v-if
var domStr = `
<ul>
{{#B}}
Hello World
{{/B}}
{{#A}}
You can see me
{{/A}}
</ul>
`
var data = {
B: false,
A: true,
}
结果展示:
可以看出,Hello World 被隐藏了,因为其对应的值为false
DOM字符串的优化
我们可以将反引号中的字符串用script包裹起来,但是该script标签的type属性必须是不能被浏览器检测到的类型,(否则会被当作js逻辑被执行),然后再利用getElementById获取该标签,这样做的好处在于,不用反引号的结构可以更直观,也会被vscode格式化
<body>
<div id="list"></div>
<script src="./mustache.js"></script>
<script type="text/template" id="domStr">
<ul>
{{#arr}}
<li>
{{name}}的爱好:
<ol>
{{#hobbies}}
<li>{{.}}</li>
{{/hobbies}}
</ol>
</li>
{{/arr}}
</ul>
</script>
<script>
// 向外暴漏一个mustache对象
// console.log(mustache)
// 1.获取script标签
const domStr = document.getElementById("domStr").innerHTML
// 2.创建一个对象,存放需要遍历的数据
var data = {
arr: [
{ name: "wsj", hobbies: ["吃饭", "睡觉", "打豆豆"] },
{ name: "ddd", hobbies: ["跑步", "游泳", "骑行"] },
{ name: "study", hobbies: ["打游戏"] },
],
}
// 3.使用mustache.render()方法,其中有两个参数,第一个放dom字符串,第二个存放需要转换为视图的数据
const listStr = mustache.render(domStr, data)
console.log(listStr)
// 4.把mustache生成的dom结构字符串添加至dom元素中
var list = document.getElementById("list")
list.innerHTML = listStr
</script>
</body>
结果展示:
最终总结:
四种不同的方法都是生成DOM字符串,然后将其添加至DOM的innerHTML中,但是明显的一代更比一代强,经过技术不断地迭代更新,大佬们研究出了mustache模板,通过其render方法(几乎只用这个方法),可以优雅的将数据渲染至DOM中,而我们所需要研究的不仅仅是mustache怎么使用,而是其在vue中所担当的角色,以及其底层原理。下篇文章讲述的是mustache的底层原理以及在vue中的实现。