双大括号语法

  • 如果我们希望把数据显示到模板(template)中,使用最多的语法是 “Mustache”语法 (双大括号) 的文本插值。
    • 并且我们前端提到过,data返回的对象是有添加到Vue的响应式系统中;
    • data中的数据发生改变时,对应的内容也会发生更新
    • 当然,Mustache中不仅仅可以是data中的属性,也可以是一个JavaScript的表达式
  • 另外这种用法是错误的:

v-once指令(了解)

  • v-once用于指定元素或者组件只渲染一次:
    • 当数据发生变化时,元素或者组件以及其所有的子元素将视为静态内容并且跳过;
    • 该指令可以用于性能优化

  • 如果是子节点,也是只会渲染一次:

v-html

  • 默认情况下,如果我们展示的内容本身是 html 的,那么vue并不会对其进行特殊的解析
    • 如果我们希望这个内容被Vue可以解析出来,那么可以使用 v-html 来展示;

v-pre

  • v-pre用于跳过元素和它的子元素的编译过程,显示原始的Mustache标签:
    • 跳过不需要编译的节点,加快编译的速度;

v-bind

绑定基本属性

  • v-bind用于绑定一个或多个属性值,或者向另一个组件传递props值(这个学到组件时再介绍);

  • 在开发中,有哪些属性需要动态进行绑定呢?

    • 还是有很多的,比如图片的链接src、网站的链接href、动态绑定一些类、样式等等

      ![](https://cdn.nlark.com/yuque/0/2023/png/35551100/1688889299083-ba6d24a0-9ad6-4505-bb09-3db0e7b03b2e.png)
      
  • v-bind有一个对应的语法糖,也就是简写方式

  • 在开发中,我们通常会使用语法糖的形式,因为这样更加简洁。

绑定class属性

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<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>
<style>
.active {
color: red;
}
</style>
</head>

<body>

<div id="app">
<!-- 1.基本绑定class -->
<h2 :class="classes">Hello World</h2>

<!-- 2.动态class可以写对象语法 -->
<button :class=" isActive ? 'active': '' " @click="btnClick">我是按钮</button>

<!-- 2.1.对象语法的基本使用(掌握) { key : value }value为true时,显示key的class,为false时不显示-->
<button :class="{ active: isActive }" @click="btnClick">我是按钮</button>

<!-- 2.2.对象语法的多个键值对 -->
<button :class="{ active: isActive, why: true, kobe: false }" @click="btnClick">我是按钮</button>

<!-- 2.3.动态绑定的class是可以和普通的class同时的使用 -->
<button class="abc cba" :class="{ active: isActive, why: true, kobe: false }" @click="btnClick">我是按钮</button>

<!-- 2.4.动态绑定的class是可以和普通的class同时的使用 -->
<button class="abc cba" :class="getDynamicClasses()" @click="btnClick">我是按钮</button>

<!-- 3.动态class可以写数组语法(了解) -->
<h2 :class="['abc', 'cba']">Hello Array</h2>
<h2 :class="['abc', className]">Hello Array</h2>
<h2 :class="['abc', className, isActive? 'active': '']">Hello Array</h2>
<h2 :class="['abc', className, { active: isActive }]">Hello Array</h2>
</div>

<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({
// data: option api
data: function () {
return {
classes: "abc cba nba",
isActive: false,
className: "why"
}
},

methods: {
btnClick: function () {
this.isActive = !this.isActive
},

getDynamicClasses: function () {
return { active: this.isActive, why: true, kobe: false }
}
}
})

// 2.挂载app
app.mount("#app")
</script>
</body>

</html>

绑定style属性

  • 我们可以利用v-bind:style来绑定一些CSS内联样式
    • 这次因为某些样式我们需要根据数据动态来决定;
    • 比如某段文字的颜色,大小等等;
  • CSS property 名可以用驼峰式 (camelCase) 短横线分隔 (kebab-case,记得用引号括起来) 来命名;
  • 绑定class有两种方式:
    • 对象语法
    • 数组语法
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
40
41
42
43
44
45
46
<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>

<div id="app">
<!-- 1.普通的html写法 -->
<h2 style="color: red; font-size: 30px;">哈哈哈哈</h2>

<!-- 2.style中的某些值, 来自data中 -->
<!-- 2.1.动态绑定style, 在后面跟上 对象类型 (重要)-->
<h2 v-bind:style="{ color: fontColor, fontSize: fontSize + 'px' }">哈哈哈哈</h2>
<!-- 2.2.动态的绑定属性, 这个属性是一个对象 -->
<h2 :style="objStyle">呵呵呵呵</h2>

<!-- 3.style的数组语法 -->
<h2 :style="[objStyle, { backgroundColor: 'purple' }]">嘿嘿嘿嘿</h2>
</div>

<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({
// data: option api
data: function() {
return {
fontColor: "blue",
fontSize: 30,
objStyle: {
fontSize: '50px',
color: "green"
}
}
},
})

// 2.挂载app
app.mount("#app")

</script>
</body>
</html>

动态绑定属性

  • 在某些情况下,我们属性的名称可能也不是固定的:
    • 前端我们无论绑定src、href、class、style,属性名称都是固定的;
    • 如果属性名称不是固定的,我们可以使用 :[属性名]=“值”的格式来定义;
    • 这种绑定的方式,我们称之为动态绑定属性
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
<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>

<div id="app">
<h2 :[name]="'aaaa'">Hello World</h2>
</div>

<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({
// data: option api
data: function() {
return {
name: "class"
}
},
})

// 2.挂载app
app.mount("#app")
</script>
</body>
</html>

绑定一个对象

  • 如果我们希望将一个对象的所有属性,绑定到元素上的所有属性,应该怎么做呢?
    • 非常简单,我们可以直接使用 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
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<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>

<div id="app">
<h2 :name="name" :age="age" :height="height">Hello World</h2>

<!-- v-bind绑定对象: 常用来给组件传递参数 -->
<h2 v-bind="infos">Hello Bind</h2>
</div>

<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({
// data: option api
data: function () {
return {
infos: { name: "why", age: 18, height: 1.88, address: "广州市" },

name: "why",
age: 18,
height: 1.88
}
},
})
// 2.挂载app
app.mount("#app")
</script>
</body>

</html>

绑定事件

v-on绑定事件

  • v-on的使用:
    • 缩写:@
    • 预期:Function | Inline Statement | Object
    • 参数:event
    • 修饰符
      • .stop - 调用 event.stopPropagation()。
      • .prevent - 调用 event.preventDefault()。
      • .capture - 添加事件侦听器时使用 capture 模式。
      • .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
      • .{keyAlias} - 仅当事件是从特定键触发时才触发回调。
      • .once - 只触发一次回调。
      • .left - 只当点击鼠标左键时触发。
      • .right - 只当点击鼠标右键时触发。
      • .middle - 只当点击鼠标中键时触发。
      • .passive - { passive: true } 模式添加侦听器
    • 用法:绑定事件监听
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<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>
<style>
.box {
width: 100px;
height: 100px;
background-color: orange;
margin-top: 10px;
}
</style>
</head>
<body>

<div id="app">
<!-- 1.基本的写法 -->
<div class="box" v-on:click="divClick"></div>

<!-- 2.语法糖写法(重点掌握) -->
<div class="box" @click="divClick"></div>

<!-- 3.绑定的方法位置, 也可以写成一个表达式(不常用, 不推荐) -->
<h2>{{ counter }}</h2>
<button @click="increment">+1</button>
<button @click="counter++">+1</button>

<!-- 4.绑定其他方法(掌握) -->
<div class="box" @mousemove="divMousemove"></div>

<!-- 5.元素绑定多个事件(掌握) -->
<div class="box" @click="divClick" @mousemove="divMousemove"></div>
<!-- <div class="box" v-on="{ click: divClick, mousemove: divMousemove }"></div> -->
<!-- <div class="box" @="{ click: divClick, mousemove: divMousemove }"></div> -->
</div>

<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({
// data: option api
data: function() {
return {
counter: 0
}
},
methods: {
divClick() {
console.log("divClick")
},
increment() {
this.counter++
},
divMousemove() {
console.log("divMousemove")
}
}
})

// 2.挂载app
app.mount("#app")
</script>
</body>
</html>

v-on参数传递

  • 当通过methods中定义方法,以供@click调用时,需要注意参数问题:
  • 情况一:如果该方法不需要额外参数,那么方法后的()可以不添加。
    • 但是注意:如果方法本身中有一个参数,那么会默认将原生事件event参数传递进去
  • 情况二:如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件。
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<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>

<div id="app">
<!-- 1.默认传递event对象 -->
<button @click="btn1Click">按钮1</button>

<!-- 2.只有自己的参数 -->
<button @click="btn2Click('why', age)">按钮2</button>

<!-- 3.自己的参数和event对象 -->
<!-- 在模板中想要明确的获取event对象: $event -->
<button @click="btn3Click('why', age, $event)">按钮3</button>
</div>

<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({
// data: option api
data: function() {
return {
message: "Hello Vue",
age: 18
}
},
methods: {
// 1.默认参数: event对象
// 总结: 如果在绑定事件的时候, 没有传递任何的参数, 那么event对象会被默认传递进来
btn1Click(event) {
console.log("btn1Click:", event)
},

// 2.明确参数:
btn2Click(name, age) {
console.log("btn2Click:", name, age)
},

// 3.明确参数+event对象
btn3Click(name, age, event) {
console.log("btn3Click:", name, age, event)
}
}
})

// 2.挂载app
app.mount("#app")
</script>
</body>
</html>

v-on的修饰符

  • v-on支持修饰符,修饰符相当于对事件进行了一些特殊的处理:
    • .stop - 调用 event.stopPropagation()。
    • .prevent - 调用 event.preventDefault()。
    • .capture - 添加事件侦听器时使用 capture 模式。
    • .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
    • .{keyAlias} - 仅当事件是从特定键触发时才触发回调。
    • .once - 只触发一次回调。
    • .left - 只当点击鼠标左键时触发。
    • .right - 只当点击鼠标右键时触发。
    • .middle - 只当点击鼠标中键时触发。
    • .passive - { passive: true } 模式添加侦听器
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
40
41
42
43
44
45
46
47
48
49
50
<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>
<style>
.box {
width: 100px;
height: 100px;
background-color: orange;
}
</style>
</head>

<body>

<div id="app">
<div class="box" @click="divClick">
<button @click.stop="btnClick">按钮</button> // 原本事件:点击btn按钮,会冒泡到div中
</div>
</div>

<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({
// data: option api
data: function () {
return {
message: "Hello Vue"
}
},
methods: {
btnClick (event) {
console.log("btnClick")
},
divClick () {
console.log("divClick")
}
}
})

// 2.挂载app
app.mount("#app")
</script>
</body>

</html>

条件渲染

v-if、v-else、v-else-if

  • v-if、v-else、v-else-if用于根据条件来渲染某一块的内容:

    • 这些内容只有在条件为true时,才会被渲染出来;

    • 这三个指令与JavaScript的条件语句if、else、else if类似;

  • v-if的渲染原理:

    • v-if是惰性的;
    • 当条件为false时,其判断的内容完全不会被渲染或者会被销毁掉;
    • 当条件为true时,才会真正渲染条件块中的内容;

template元素

  • 因为v-if是一个指令,所以必须将其添加到一个元素上:
    • 但是如果我们希望切换的是多个元素呢?
    • 此时我们渲染div,但是我们并不希望div这种元素被渲染;
    • 这个时候,我们可以选择使用template;
  • template元素可以当做不可见的包裹元素,并且在v-if上使用,但是最终template不会被渲染出来:
    • 有点类似于小程序中的block

v-show

  • v-show和v-if的用法看起来是一致的,也是根据一个条件决定是否显示元素或者组件:

    ![](https://cdn.nlark.com/yuque/0/2023/png/35551100/1688891705236-1173d386-f357-4a90-8b5e-ee3334763c21.png)
    

v-show和v-if的区别

  • 首先,在用法上的区别:
    • v-show是不支持template;
    • v-show不可以和v-else一起使用;
  • 其次,本质的区别:
    • v-show元素无论是否需要显示到浏览器上,它的DOM实际都是有存在的,只是通过CSS的display属性来进行切换;
    • v-if当条件为false时,其对应的原生压根不会被渲染到DOM中;
  • 开发中如何进行选择呢?
    • 如果我们的原生需要在显示和隐藏之间频繁的切换,那么使用v-show;
    • 如果不会频繁的发生切换,那么使用v-if;