小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
1. 绑定 class 属性
开发中,我们经常需要根据不同情况给元素设置不同的 class,因为不同的 class 可以呈现不同的效果,比如:
- 当数据为某个状态时,字体显示为红色;
- 当数据为另一个状态时,字体显示为黑色;
所以很多时候我们需要根据不同的数据来动态决定元素的 class。因此,我们可以使用 v-bind 来动态绑定 class 属性。
可以使用结果的类型是字符串的表达式绑定 class:
<p :class="className">{{ message }}</p>
但还有另外两种方式来绑定 class:对象或数组(表达式结果的类型是对象或数组)。
1.1. 对象语法
可以传给 :class (v-bind:class 的简写)一个对象,以动态地切换 class:
<div :class="{ active: isActive }"></div>
上面的语法表示 active 这个 class 是否存在将取决于数据属性 isActive 的 truthiness1,当数据属性 isActive 为真值时,则上面的 div 元素上将添加上 active 这个 class,否则,将不会添加上 active 这个 class。
动态的 class(:class 指令)也可以和普通的 class 属性共存,它们会进行合并,但不会做去重操作。比如有如下模板:
<div
class="abc active"
:class="{ active: isActive, classB: true, 'text-danger': hasError }"
>
{{ message }}
</div>
和如下数据:
data() {
return {
message: '你好啊',
isActive: true,
hasError: false
}
}
则渲染的结果为:
<div class="abc active active classB">你好啊</div>
绑定的对象可以不内联在模板里,我们可以将它抽取到一个组件实例的数据属性中,再绑定这个属性:
<div class="abc active" :class="classObj">{{ message }}</div>
data() {
return {
message: '你好啊',
isActive: true,
hasError: false,
// 注意:因为 data() 返回的对象最终是要交给响应式系统处理的,所以它最好是一个纯对象,
// 不应该让某个属性的值又去引用另一个属性的值,而是应该直接使用有关属性的初始值(比如这里的
// active: isActive、'text-danger': hasError,就应该把 isActive 换成它对应的值 true,
// 把 hasError 换成它对应的值 false)
classObj: {
active: true,
classB: true,
'text-danger': false
}
}
}
完整代码如下:
<!DOCTYPE html>
<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"></div>
<template id="my-app">
<!-- 1. 普通的绑定方式 -->
<p :class="className">{{ message }}</p>
<!-- 2. 对象绑定 -->
<!-- 动态决定 class 是否添加,格式:{ 类名/[变量名]: 表达式/数据属性 } -->
<p :class="{ aaa: true }"></p>
<p :class="{ aaa: true && !'' }"></p>
<p :class="{ [aaa]: true && !'' }"></p>
<p :class="{ bbb: isActive }"></p>
<!-- 小案例演示:点击按钮切换文本颜色 -->
<div :class="{ active: isActive }">{{ message }}</div>
<button @click="toggle">切换</button>
<!-- 对象可以有多个键值对,所以可以在对象中动态绑定多个 class -->
<div :class="{ active: isActive, classB: true, 'text-danger': hasError }">{{ message }}</div>
<!-- 动态的 class 可以和普通的 class 属性共存,它们会进行合并,但不会做去重操作 -->
<div
class="abc active"
:class="{ active: isActive, classB: true, 'text-danger': hasError }"
>
{{ message }}
</div>
<!-- 将对象抽取到一个数据属性中,绑定这个数据属性 -->
<div class="abc active" :class="classObj">{{ message }}</div>
<!-- 调用一个返回对象的方法,绑定其返回的对象(调用方法的方式不常用,computed 方式更常用) -->
<div class="abc active" :class="getClassObj()">{{ message }}</div>
<!-- 还可以绑定一个返回对象的计算属性(computed),这是一个常用且强大的模式,后面讲到 computed 时再说 -->
</template>
<script src="./js/vue.js"></script>
<script>
const App = {
data() {
return {
message: '你好啊',
className: 'class-a',
aaa: 'ca',
isActive: true,
hasError: false,
// 注意:因为 data() 返回的对象最终是要交给响应式系统处理的,所以它最好是一个纯对象,
// 不应该让某个属性的值又去引用另一个属性的值,而是应该直接使用有关属性的初始值(比如这里的
// active: isActive、'text-danger': hasError,就应该把 isActive 换成它对应的值 true,
// 把 hasError 换成它对应的值 false)
classObj: {
active: true,
classB: true,
'text-danger': false
}
}
},
methods: {
toggle() {
this.isActive = !this.isActive;
},
getClassObj() {
return {
active: true,
classB: true,
'text-danger': false
};
}
},
template: '#my-app'
};
Vue.createApp(App).mount('#app');
</script>
</body>
</html>
1.2. 数组语法
我们可以把一个数组传给 :class,以应用一个 class 列表:
<div :class="['aaa', activeClass, errorClass]"></div>
data() {
return {
activeClass: 'active',
errorClass: 'text-danger'
}
}
渲染的结果为:
<div class="aaa active text-danger"></div>
数组中还可以使用三元表达式,以根据条件切换 class 或决定是否添加相应的 class:
<div :class="['aaa', isActive ? 'active' : 'deactive']"></div>
<div :class="['aaa', isActive ? 'active' : '']"></div>
data() {
return {
isActive: true
}
}
这样写将始终添加 aaa 这个 class,但只有在 isActive 为真值(truthy)时才添加 active 这个 class。
数组中也可以使用对象语法:
<div :class="['aaa', { active: isActive }]"></div>
因此,当有多个条件 class(多个三元表达式)时,就可以使用对象语法进行简化了。
此外,数组中的 class 不会自动去重:
<div :class="['aaa', activeClass, errorClass, bbb]"></div>
data() {
return {
activeClass: 'active',
errorClass: 'text-danger',
bbb: 'aaa'
}
}
渲染的结果为:
<div class="aaa active text-danger aaa"></div>
Footnotes
-
除了
false、0、-0、0n、""、null、undefined、NaN这8个值以外的值都是真值(truthy),只有这8个值是假值(falsy)。 ↩