Vue笨蛋学原理:数据(data)是如何出现在页面上的?
程序员文章站
2024-02-02 11:17:16
...
本篇只是为了让大家看懂原理,写出来的代码并不是Vue源码
<div id="app">
<h1> {{ name }} </h1>
<p> {{ mes }} </p>
</div>
console.log(app) // 打印出来看一下
new Vue({
el:'#app',
data:{
name:'刘亦菲',
mes:'我爱你'
}
})
console.log(app) // 在这里打印出来看一下
- 可以看出来,虽然两个都是app,但是在两个不同的div里出现的内容是不同的,而且后者是渲染在页面上的,鼠标放上去,页面有高亮反应
- 那么,Vue是怎么把实例中的data里的name和mes渲染到页面上的呢
四个步骤
- 找到标签
- 拿到数据
- 找到双大括号,进行替换
- 渲染上去
找到标签
重新创建一个新的页面,把引入的Vue文件删除
let tempNode = document.querySelector('#app')
拿到数据
let data = {
name:'刘亦菲',
mes:'我爱你'
}
找到双大括号,将数据与模板结合
- 先找到模板的所有子元素
- 一般都是使用递归
- 在真正的Vue源码中是 DOM–>字符串模板–>VNode–>真正的DOM
function compiler(template,data) {
let chileNodes = template.childeNode // 拿到所有子节点
}
- 我们知道,DOM节点对应不同的数值,代表着不同的节点
- 我们来遍历所有的子节点,当这个节点是元素节点的时候,我们就需要进行递归,因为他可能是个嵌套标签
- 考虑它有没有子元素,是否需要将其子元素进行判断是否要插值
function compiler(template,data) {
let chileNodes = template.childNodes
for(let i = 0; i < childNodes.length; i++) {
let type = childNodes[i].nodeType
if(type === 3){ // 文本节点
} else if(type === 1) { // 元素节点
compiler(childNodes[i],data)
}
}
}
- 当这个节点是文本节点的时候,就说明这里面可能有咱们需要的双大括号
// 使用正则来选择
let reg = /\{\{(.+?)\}\}/g;
if(type === 3){
let txt = childNodes[i].nodeValue // 该属性只有文本节点才有意义
txt = txt.replace(reg,function(_,g) {
let key = g.trim(); // 剔除掉不必要的东西
let value = data[key] // 把保存在data里的对应的数据赋值给选出来的值
return value // 返回被data赋值后的新的值
})
childNodes[i].nodeValue = txt
}
- 可能对replace的用法不太熟悉,我们来看一下
- 所匹配到的东西是函数的第一个参数
- 函数的返回值用来替换被匹配到的东西
- 函数的第个参数以及以后的参数是正则表达式里的对应的第几组
把数据渲染到页面上
-
此时是没有生成新的template, 所以这里看到的是直接在页面中就更新的数据,因为DOM是引用类型
-
这样做模板就没有了
-
我们不会去直接改变模板,所以clone一下
let generateNode = tempNode.cloneNode(true)
console.log(tempNode)
// compiler(tempNode,data)
compiler(generateNode,data)
console.log(tempNode)
app.parentNode.replaceChild(generateNode,app)
- 看一下打印到页面的效果
看一下完整的代码
<body>
<div id="app">
<h1> {{ name }} </h1>
<p> {{ mes }} </p>
</div>
// js部分
<script>
let tempNode = document.querySelector('#app')
let data = {
name:'刘亦菲',
mes:'我爱你'
}
let reg = /\{\{(.+?)\}\}/g;
function compiler(template,data) {
let childNodes = template.childNodes
for(let i = 0; i < childNodes.length; i++) {
let type = childNodes[i].nodeType
if(type === 3) {
let txt = childNodes[i].nodeValue
txt = txt.replace(reg,function(_,g) {
let key = g.trim();
let value = data[key]
return value
})
childNodes[i].nodeValue = txt
} else if(type === 1) {
compiler(childNodes[i],data)
}
}
}
let generateNode = tempNode.cloneNode(true)
console.log(tempNode)
// compiler(tempNode,data)
compiler(generateNode,data)
console.log(tempNode)
app.parentNode.replaceChild(generateNode,app)
</script>
</body>
上一篇: IntelliJ IDEA 配置maven并导入依赖jar包
下一篇: vue之mvvm原理解析