vue2之模板

222 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情

在vue中我们常用到模板,正是这些模板才让我们能将DOM与动态数据绑定在一起,而不是像原生js那样操作DOM节点去绑定数据。这篇文章我们来介绍一下模板相关的知识,比如编译原理,语法等。

模板

模板其实就是vue里面的View, 也就是视图。可以理解成被vue实际控制的页面片段。在vue中渲染流程其实就是将模板转成虚拟DOM,然后再转成实际DOM的过程,而将模板转成虚拟DOM的过程其实就是我们下面要讲到的模板编译(也称为模板渲染)。

编译原理

模板编译其实就是将模板template转成render函数的过程,而渲染函数每次执行时都会生成新的vNode。模板编译可以用下面的图来表示。

image.png 未命名文件.png

1. 确认模板

对于vue项目来说,我们可以在很多地方写元素,处理一些渲染相关的操作。比如:el, template, render, $mount等。那么如何确认我们的模板内容呢?

1.1 渲染到哪个根节点上?

这个主要是根据el属性来判断,el属性值是什么,那么根节点就是什么。没有el属性的话,那么就会根据$mount挂载时去找根节点,挂载在什么上面,什么就是根节点。

1.2 渲染哪个模板到根节点上?

这个主要取决于render函数,

  • 如果有render函数的话,先执行render函数,render函数上渲染的模板优先级比template高。
  • 如果没有render函数的话,再去找是否定义了template.
    • 定义了template, 将template转成render函数所需要的格式(字符串),然后再执行render函数生成模板
    • 没有定义template, 就将根节点的outHtml的内容转成render函数所需要的格式(字符串),然后再执行render函数生成模板。

2. 将模板解析成AST

这个过程主要是通过解析器来完成的,AST其实就是用js对象来描述节点。解析器的原理是一小段一小段地截取模板字符串,每截取一小段字符串,就会根据截取出来的字符串类型触发不同的钩子函数,直到模板字符串截空停止。然后使用栈来确定层级关系。

3. 标记AST中的静态节点

Vue的数据是响应式的,但在模板中并不是所有的都是响应式的。有一些数据首次渲染后就不会再发生变化,比如v-once指定的,或者是一些不变的内容,那么对应的DOM也不会变化。优化就是深度遍历抽象语法树,按照相关条件对树节点进行标记。这些被标记的节点(静态节点)也就是不会发生变化的节点,我们就可以跳过对它们的比对,对运行时的模板起到很大的优化作用。

4. 将AST转化成渲染函数的字符串

这个过程其实就是递归AST生成字符串,先生成根字符串,然后再生成后面的子节点字符串,将子节点字符串拼接在根节点字符串上,层层递进,最后就可以得到一个完整的字符串。

模板语法

在vue中,模板语法主要分为两大类:插值语法和指令语法。

插值语法

插值语法就是我们常用到的{{}},这种语法主要用在标签体里面。

1. mustache语法

这种语法就是我们经常会用到的一种语法,就是将数据变量展示到template模板中。 1.1 基本用法

<div>{{msg}}</div>

data () {
    return {
      msg: ''
    };
},

1.2 js表达式用法

<div>{{num * 2 + 650}}</div>

data () {
    return {
      num: 4
    };
},

1.3 三元运算符

<div>{{num ? 1020}}</div>

data () {
    return {
      num: 4
    };
},

1.4 调用methods方法里面的方法

<div>{{consoleMsg('hello')}}</div>

consoleMsg(msg) {
  return msg;
}
2. v-once语法

v-once语法指令元素只渲染一次,后面变量无论发生什么改变,页面都不会发生变化

<div v-once>{{msg}}</div>

data () {
    return {
      msg: ''
    };
},
3. v-text语法

v-text用于更新元素的textContent,我们通常写的模板语法其实就是用来更新这个的

<div>{{msg}}</div>

// 等价于
<div v-text="msg"></div>
4. v-html语法

我们一般在{{}}里面写的或者执行返回的内容都是文本内容,如果想要往模板里面插入html内容,需要借助v-html指令来完成。

<div v-html="<span>html内容</span>"></div>
5. v-pre语法

如果某个元素使用了v-pre,那么当前元素及其子元素在模板编译阶段会被跳过,直接显示mustache标签

<div v-pre></div>

指令语法

除了上面介绍的一些插值模板语法之外,还有一种模板语法就是指令语法。指令语法是作用在标签上的,常常以v-前缀的特殊特性,比如前面看到的v-htmlv-once等。Vue指令的特性的值预期是单个JavaScript表达式。Vue指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于DOM。

v-bind

v-bind就是给元素绑定某个属性,其中属性值可以是变量或者常量

<a v-bind:href="url"></a>

// 简写形式
<a :href="url"></a>
v-on

v-on就是给元素绑定事件。

<div class="box3" v-on:click="consoleMsg('left')"></div>

// 简写方式
<div class="box3" @click="consoleMsg('left')"></div>
等等

除了上面介绍的这两种指令之外,vue还有很多其他指令,这些指令最后都能渲染出对应的属性或表现方法。