🚥Vue2 系列文章导航🚥

  1. Vue环境配置(Windows)
  2. Vue学习笔记(一):模版语法、条件渲染、列表渲染、key值管理
  3. Vue学习笔记(二):事件处理、事件传参、修饰符、数组变化侦测
  4. Vue学习笔记(三):计算属性、类与样式绑定、表单输入绑定、侦听器、模版引用
  5. Vue学习笔记(四):深入了解组件(上)
  6. Vue学习笔记(五):深入了解组件(下)
  7. Vue学习笔记(六):生命周期钩子、路由、Element Plus

一、模版语法

Vue 使用一种基于 HTML 的模板语法,使我们能够声明式地将其组件实例的数据绑定到呈现的 DOM 上。所有的 Vue 模板都是语法层面合法的 HTML,可以被符合规范的浏览器和 HTML 解析器解析。

1.文本插值

文本插值最基本的数据绑定语法,采用双大括号{ { } }的形式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<div>
<p>{{ message }}</p>
</div>
</template>

<script>
export default {
data() {
return {
message: "宝可梦百科"
}
}
}
</script>

{ { } }标签的内容将会被替代为对应组件实例中 message 属性的值,如果 message 属性的值发生了改变,{ { } } 标签内容也会更新。

因此,如果不想改变标签的内容,可以通过使用 v-once 指令执行一次性地插值,当数据改变时,插值处的内容不会更新。

1
<p v-once>该值不会改变:{{ message }}</p>

在上面的演示中,我们绑定的只是简单的属性名,但实际上,Vue在所有的数据绑定中都支持完整的 JavaScript 表达式。例如:

1
<p>{{ message.split("").reverse().join("") }}</p>

但需要注意的是,每个绑定仅支持单一表达式,也就是一段能够被求值的 JavaScript 代码。我们可以通过其能否合法放在return的后面来进行判断。

2.原始 HTML

双大括号会将数据插值为纯文本,而不是 HTML。若想插入 HTML,则需要使用v-html指令。我们可以通过下面的代码来观察两者的区别。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div>
<p>{{ PMHtml }}</p>
<p v-html = "PMHtml"></p>
</div>
</template>

<script>
export default {
data() {
return {
PMHtml: "<a href='https://wiki.52poke.com/wiki/%E4%B8%BB%E9%A1%B5'>宝可梦百科</a>"
}
}
}
</script>

1

我们可以看到,前者只是做了单纯的文本替换,后者则是将我们想要的链接成功渲染出来(渲染方式为在p标签里嵌套一个a标签)。

3.属性绑定

从前文v-html指令的使用中,我们可以想到,既然双大括号不能用于插入 HTML,那么修改 HTML 属性显然也是不行的。当我们想要响应式地绑定一个属性,应该使用v-bind指令。而如果绑定的值是null或者undefined,那么该属性将会从渲染的元素上移除。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<p v-bind:class = "testClass" v-bind:id = "testId" v-bind:title = "testTitle">小火龙</p>
</template>

<script>
export default {
data() {
return {
testClass: "火",
testId: "小火龙",
testTitle: null
}
}
}
</script>

2

我们可以看到,在 HTML 中,classid都被成功赋值,title由于被赋予的值为null而被移除。

由于v-bind指令使用过于频繁,我们可以通过简写的方式把v-bind省略,只保留冒号,如:

1
<p :class = "testClass" :id = "testId" :title = "testTitle">小火龙</p>

v-bind也可用于绑定布尔属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<button disabled>按钮A</button>
<button v-bind:disabled = "isDisabled">按钮B</button>
</template>

<script>
export default {
data() {
return {
isDisabled:false
}
}
}
</script>

当我们想要动态绑定多属性时,也可以借助 JavaScript 对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<p v-bind = Object>小火龙</p>
</template>

<script>
export default {
data() {
return {
Object: {
class: "火",
id: "小火龙"
}
}
}
}
</script>

二、条件渲染

条件渲染主要借助v-ifv-elsev-else-ifv-show指令。其具体的用法与逻辑很简单,我们可以通过下面的例子具体感受:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
<div v-if = "flag">小火龙</div>

<div v-if = "flag">妙蛙种子</div>
<div v-else>杰尼龟</div>

<div v-if = "type === 'A'">小火龙</div>
<div v-else-if = "type === 'B'">火恐龙</div>
<div v-else-if = "type === 'C'">喷火龙</div>
<div v-else>mega喷火龙X</div>

<div v-show = "flag">杰尼龟</div>
</template>

<script>
export default {
data() {
return {
flag: true,
type: "D"
}
}
}
</script>

3

有些同学可能会发现,v-ifv-show的功能似乎是一样的,那么我们又为什么要引入v-show指令呢?或者说两者有什么区别呢?

v-ifv-show区别:

v-if是“真实的”按条件渲染,因为它确保了在切换时,条件区块内的事件监听和子组件都会被销毁与重建。

同事v-if也是惰性的,如果在初次渲染时条件值为 false,则不会做任何事。条件区块只有当条件首次变为 true 时才会被渲染。

相比之下,v-show更加简单,元素无论初始条件如何,始终会被渲染,只有 CSS 的display属性会被切换。

总的来说,v-if有更高的切换开销,而v-show有更高的初始渲染开销。因此,如果需要频繁切换,则使用v-show比较好;如果在运行时绑定条件很少改变,则v-if会更合适。

三、列表渲染

我们可以使用v-for指令基于一个数组来渲染一个列表。v-for指令的值需要使用item in items形式的特殊语法,其中items是源数据的数组,而item是迭代项的别名(可自行更改)。

遍历的对象既可以是数组,也可以是对象,或者是更为复杂的对象数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<p v-for = "item in names">{{ item }}</p>
<p v-for = "item in pokemon">{{ item }}</p>
</template>

<script>
export default {
data() {
return {
names: ["小火龙","妙蛙种子","杰尼龟"],
pokemon: {
name: "小火龙",
id: 1,
system: "fire"
}
}
}
}
</script>

4

v-for也支持使用可选的参数indexkeyvalue等(value可以替换为item)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<p v-for = "(item, index) in names">{{ index }}:{{ item }}</p>
<p v-for = "(value, key, index) in pokemon">{{index}}-{{ key }}:{{ value }}</p>
</template>

<script>
export default {
data() {
return {
names: ["小火龙","妙蛙种子","杰尼龟"],
pokemon: {
name: "小火龙",
id: 1,
system: "fire"
}
}
}
}
</script>

此外,我们也可以用of作为分隔符来代替in,这更加接近JavaScript的迭代器语法:

1
<p v-for = "item of names">{{ item }}</p>

四、通过 key 管理状态

Vue 默认按照“就地更新”的策略来更新通过v-for渲染的元素列表。当数据项的顺序改变时,Vue 不会随之移动DOM元素的顺序,而是就地更新每个元素,确保它们在原本指定的索引位置上渲染。为了给 Vue 一个提示,以便它可以跟踪每个节点的标识,从而重用和重新排序现有的元素,我们需要为每一个元素对应的块提供一个唯一的 key attribute。

1
2
3
4
5
6
7
8
9
10
11
12
<template>
<p v-for = "item in names" :key = "index">{{ item }}</p>
</template>
<script>
export default {
data() {
return {
names: ["小火龙", "妙蛙种子", "杰尼龟"]
}
}
}
</script>

key在这里是通过v-blind绑定的特殊 attribute(此处的v-blind被省略)。

推荐在任何可行的时候为v-for提供一个 key attribute(在 Vue2 版本中不添加key会导致出现警告信息,而在最新的 Vue3 版本中取消了这一限制,我们以最新的 Vue3 为基准)。

key绑定的值期望是一个基础类型的值,例如字符串或number类型。一般情况下,不建议使用index作为key值,因为数据的插入和删除会导致index的改变,而我们要确保每一条数据的唯一索引不会发生变化。例如,如果对象数据存在唯一的id属性,我们可以把id属性的值作为key