Vue学习笔记(一)

模板语法

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

文本插值

最基本的数据绑定形式是文本插值,它使用的是“Mustache”语法(即双大括号):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script>
export default {
name: 'hello'
data() {
return {
msg: "神奇的语法",
hello: "Hello World"
}
}
}
</script>

<template>
<h3>模板语法</h3>
<p>{{ msg }}</p>
<p>{{ hello }}</p>
</template>

使用 JavaScript 表达式

每个绑定仅支持单一表达式,也就是一段能够被求值的 JavaScript 代码。一个简单的判断方法是否可以合法地写在return后面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script>
export default {
name: "HelloWorld",
data() {
return {
msg: "神奇的语法",
number: 10,
ok: true,
message: "大家好"
}
}
}
</script>

<template>
<h3>模板语法</h3>
<p>{{ msg }}</p>
<p>{{ number + 1 }}</p>
<p>{{ ok ? 'Yes' : 'No' }}</p>
<p>{{ message.split('').reverse().join('') }}</p>
</template>

注意
以下这些表达式会在当前活动实例的数据作用域下作为 JavaScript 被解析。有个限制就是,每个绑定都只能包含单个表达式,所以下面的例子都不会生效。

1
2
3
4
5
<!--  这是语句,不是表达式:-->
{{ var a = 1 }}

<!-- 流程控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}

原始 HTML

双大括号将会将数据插值为纯文本,而不是 HTML。若想插入 HTML,需要使用 v-html指令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
export default {
name: "HelloWorld",
data() {
return {
msg: "神奇的语法",
number: 10,
ok: true,
message: "大家好",
rawHtml: "<a href='https://www.baidu.com'>百度</a>",
}
}
}
</script>

<template>
<h3>模板语法</h3>
<p>{{ msg }}</p>
<p>{{ number + 1 }}</p>
<p>{{ ok ? 'Yes' : 'No' }}</p>
<p>{{ message.split('').reverse().join('') }}</p>
<p>{{ rawHtml }}</p>
<p v-html="rawHtml"></p>
</template>

运行截图:

20241023195329

属性绑定

双大括号不能再 HTML attributes 中使用。想要响应式地绑定一个 attributte,应该使用 v-bind指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script>
export default {
data() {
return {
dynamicClass: "appclass",
dynamicId: "appId",
dynamicTitle: null
}
}
}
</script>

<template>
<div v-bind:id="dynamicId" v-bind:class="dynamicClass" v-bind:title="dynamicTitle">测试</div>
</template>

<style>

.appclass{
color: red;
font-size: 30px;
}
</style>

v-bind指令指示 Vue 将元素的 idattribute 与组件的 dybanucId属性保持一致。如果绑定的值是 null或者 undefined,那么该 attribute 将会从渲染的的元素上移除。

20241024181245

简写

因为 v-bind非常常用,我们提供了特定的简写语法 :,即直接将 v-bind省去

1
<div :id="dynamicId" :class="dynamicClass" :title="dynamicTitle">测试</div>

布尔型 attribute

布尔型 attribute 依据 true/false 值来决定 attribute 是否应该存在于该元素上,disabled就是最常见的例子之一。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<script>
export default {
data() {
return {
dynamicClass: "appclass",
dynamicId: "appId",
dynamicTitle: undefined,
isButtonDisabled: false
}
}
}
</script>

<template>
<div :id="dynamicId" :class="dynamicClass" :title="dynamicTitle">测试</div>
<button :disabled="isButtonDisabled">Button</button>
</template>

<style>

.appclass{
color: red;
font-size: 30px;
}
</style>

动态绑定多个值

如果你有像这样的一个包含多个 attribute 的 JavaScript 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<script>
export default {
data() {
return {
dynamicClass: "appclass",
dynamicId: "appId",
dynamicTitle: undefined,
isButtonDisabled: false,
objectOfAttrs: {
id: "appId",
class: "appclass"
}
}
}
}
</script>

<template>
<div :id="dynamicId" :class="dynamicClass" :title="dynamicTitle">测试1</div>
<button :disabled="isButtonDisabled">Button</button>
<div v-bind:="objectOfAttrs">测试2</div>
</template>

<style>

.appclass{
color: red;
font-size: 30px;
}
</style>

条件渲染

Vue中,提供了条件渲染,这类似于 JavaScript中的条件语句。

  1. v-if
  2. v-else
  3. v-else-if
  4. v-show

v-if

v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 true 值的时候被渲染。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
export default {
data() {
return {
flag: true
}
}
}
</script>

<template>
<h3>条件渲染</h3>
<div v-if="flag">你能看见我吗</div>
</template>

v-else

你可以使用 v-else 指令来表示 v-if 的“else 块”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
export default {
data() {
return {
flag: false
}
}
}
</script>

<template>
<h3>条件渲染</h3>
<div v-if="flag">你能看见我吗</div>
<div v-else>那你还是看看我吧!</div>
</template>

v-else-if

顾名思义,v-else-if提供的是相应于 v-if的 else if 区块。它可以连续多次重复使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script>
export default {
data() {
return {
flag: false,
type: "D",
}
}
}
</script>

<template>
<h3>条件渲染</h3>
<div v-if="flag">你能看见我吗</div>
<div v-else>那你还是看看我吧!</div>
<div v-if="type==='A'">A</div>
<div v-else-if="type==='B'">B</div>
<div v-else-if="type==='C'">C</div>
<div v-else>Not A/B/C</div>
</template>

v-show

另一个用于条件性展示元素的选项是 v-show 指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script>
export default {
data() {
return {
flag: true,
type: "D",
}
}
}
</script>

<template>
<h3>条件渲染</h3>
<div v-if="flag">你能看见我吗</div>
<div v-else>那你还是看看我吧!</div>
<div v-if="type==='A'">A</div>
<div v-else-if="type==='B'">B</div>
<div v-else-if="type==='C'">C</div>
<div v-else>Not A/B/C</div>
<div v-show="flag">你可以看看我吗?</div>
</template>

v-if vs v-show 的区别

v-if 是“真正”的条件渲染,因为它会确保在切换过程中,条件块内的事件监听器和子组件适当地被销毁和重建。

v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

一般来说,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
<script>
export default {
data() {
return{
names: ["潘家辉","大佬","真强","!"]
}
}
}
</script>

<template>
<h3>列表渲染</h3>
<p v-for="item in names">{{ item }}</p>
</template>

复杂数据

大多数情况下,我们渲染的数据源来于网络请求,也就是 JSON格式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<script>
export default {
data() {
return{
names: ["潘家辉","大佬","真强","!"],
result: [{
"id": 2261677,
"name": "我不是药神",
"score": 9.7,
"release_date": "2018-07-05",
"cover_url": "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2561305377.jpg"
}, {
"id": 26752088,
"name": "疯狂动物城",
"score": 9.2,
"release_date": "2016-03-04",
"cover_url": "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2315672647.jpg"
}, {
"id": 1295644,
"name": "阿甘正传",
"score": 9.4,
"release_date": "1994-06-23",
"cover_url": "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p510876377.jpg"
}],
}
}
}
</script>

<template>
<h3>列表渲染</h3>
<p v-for="item in names">{{ item }}</p>
<div v-for="item in result">
<p>{{ item.name }}</p>
<p>{{ item.score }}</p>
<p>{{ item.release_date }}</p>
<img :src="item.cover_url" alt="tu">
</div>
</template>

v-for也支持使用可选的第二个参数表示当前项的位置索引

1
2
3
<p v-for="(item,index) in names">
{{ item }}-{{ index }}
</p>

也可以使用 of作为分隔符来替代 in,这更接近 JavaScript 的迭代器语法

1
2
3
<p v-for="(item,index) of names">
{{ item }}-{{ index }}
</p>

v-for 与对象

也可以使用 v-for来遍历一个对象的所有属性。

1
2
3
4
5
6
7
8
userInfo: {
name: "潘家辉",
age: 18,
sex: "男"
}
<div>
<p v-for="(value,key,index) of userInfo">{{ value }}-{{ key }}-{{ index }}</p>
</div>

运行截图

20241025122819

补充-通过 key 管理状态

当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。

为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一的 key attribute:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
export default {
data(){
return{
names: ['Alice', 'Bob', 'Cathy']
}
}
}
</script>

<template>
<h3>Key属性添加到v-for中</h3>
<p v-for="(item,index) in names" :key="index">{{ item }}</p>
</template>

温馨提示

  1. key在这里是通过一个 v-bind绑定的特殊 attribute。
  2. 推荐在任何可行的时候为 v-for提供一个 keyattribute。
  3. key绑定的值期望是一个基础类型的值,例如字符串或 number 类型。

key 的来源

不要使用 index作为 key的值,我们要确保每一条数据的唯一索引不会发生变化。
一般使用数据库的唯一 id