本页目录
数据绑定的一个常见需求场景是操纵元素的 CSS class 列表和内联样式。
因为 class 和 style 都是 attribute,我们可以和其他 attribute 一样使用 v-bind 将它们和动态的字符串绑定。
但是,在处理比较复杂的绑定时,通过拼接生成字符串是麻烦且易出错的。
因此,Vue 专门为 class 和 style 的 v-bind 用法提供了特殊的功能增强。
除了字符串外,表达式的值也可以是对象或数组。
能动态的修改各类样式
提要:
- v-bind:指令会将普通属性的值变为表达值
- 使用
v-bind指令的class属性值不再是字符串,而是表达式。 表达式里的className不是一个普通的字符,而是一个变量,Vue实例data属性中的数据。 - v-bind 在处理 class 和 style 时, 表达式除了可以使用字符串之外,还可以是对象或数组。
- v-bind:class 可以简写为 :class。
v-bind 指令可以让我们将属性值关联到 Vue data数据中,这样的属性,我们称作为属性的动态绑定。
属性的动态绑定比较符合 vue 以数据为驱动的模式,如果需要修改那个属性值,就可以直接通过修改Vue数据即可。
注意:
动态属性绑定, 在我们需要的时候在使用,如果一个属性的是是固定的,并不会在未来发生改变,就没有必要动态绑定属性.
但在属性动态绑定过程中有两个属性比较特殊,这两个属性就是 class 和 style 属性,
在将 v-bind 用于 class 和 style 时,Vue.js 做了专门的增强。
表达式结果的类型除了字符串之外,还可以是对象或数组。
用法示例
<h2 :class="msg">Hello World</h2>使用动态绑定指令, 那么此时 class 后面的引号不再是字符串,而是一个JavaScript表达式。
msg也就成为了一个变量,因此此时 h2 标签的类名不是字符串msg, 而是 data 数据中msg中的值、
演示代码
<script src="https://unpkg.com/vue@next"></script> <div id="app">
<!-- 未使用动态绑定的class属性 --> <div class="msg">hello world</div>
<!-- 使用v-bind 动态绑定class属性 --> <div :class="msg">你好! Vue</div> </div>
<script> const App = { data() { return { msg: 'nbox', } }, } const app = Vue.createApp(App); app.mount("#app"); </script> <style> .nbox { color: red; } </style>浏览器执行效果
原网页中的可执行演示已停用,以下完整保留为静态 HTML 代码。
<script src="https://unpkg.com/vue@next"></script> <div id="npp">
<!-- 未使用动态绑定的class属性 --> <div class="msg">hello world</div>
<!-- 使用v-bind 动态绑定class属性 --> <div :class="msg">你好! Vue</div>
</div>
<script> const Npp = { data() { return { msg: 'nbox', } }, }
const npp = Vue.createApp(Npp); npp.mount("#npp");
</script> <style> .nbox { color: red; } </style>
💛Class
属性绑定
我们可以为 v-bind:class 设置一个对象,从而动态的切换 class:
<div :class="{ 'active': isActive }"></div>如果 isActive 为真,则在浏览器中渲染如下
<div class="active"></div>语法说明:
- 上面的语法表示:
active这个 类名是否存在 将取决于数据属性isActive的 布尔特性。 - 如果
isActive的值为true, 那么div将有类名active否则,div没有box类名 - 需要注意,此时
active就是一个类名,并不是 vue 中的数据属性
多个对象
<div :class="{'active' : isActive, 'text-danger' : hasError}"></div>浏览器渲染
<div class="active text-danger"></div>与普通的 class 属性共存
<div class="static" :class="{ 'active' : isActive, 'text-danger' : hasError }"> </div>浏览器渲染
<div class="static active text-danger"></div>错误示例,下列两个代码不会生效
<h2 :class="msg box">Hello World</h2><h2 :class="isTrue ? msg : ''" :class="flag ? 'haha' : ''">你好</h2>class 绑定对象
如果您的 class 属性较多,我推荐您绑定对象,以便您的操作和代码的整洁性
<div id="app"> <div :class="classObject"></div></div>const app = { data() { return { classObject: { 'active': false, 'text-danger': true } } }}浏览器渲染
<div class="text-danger"></div>绑定一个返回对象的计算属性。这是一个常用且强大的模式
<div id="app"> <div :class="classObject"></div></div> const app = { data() { return { isActive: true, error: false, } }, computed: { classObject() { return { active: this.isActive, 'text-danger': !this.error, } } } }浏览器渲染
<div class="active text-danger"></div>class 绑定数组(方法一)
<div id="app"> <div class="static" :class="[activeClass, errorClass]"></div></div>const app = { data() { return { activeClass: 'active', errorClass: 'text-danger' } }}class 绑定数组(方法二)
<div :class="classObject"></div> const App = { data() { return { classObject: ["static", "active", { "text-danger": true }], } }, }以上两种方法,浏览器渲染均为
<div class="static active text-danger"></div>使用三元表达式来切换列表中的 class
<div id="app"> <div :class="[isActive ? activeClass : '', errorClass]"></div></div>const app = { data() { return { isActive: false, activeClass: 'active', errorClass: 'text-danger' } }}浏览器渲染为
<div class="text-danger"></div>在代码isActive ? activeClass : ''中,因为isActive是假,表达式的值为第三个,为空值,当isActive为真时,表达式的值为第二个,即为activeClass。
💛style(内联样式)
动态绑定 style 属性说明:
- 如果使用动态绑定属性方法绑定行内样式,那么 style 属性值将不再是字符串,而是表达式,
- 动态绑定 style 的值既然是表达式,那么就可以在表达式中使用对象.
- 如果值为对象,那么对象的属性名则为 CSS 样式属性, 值为样式的值。
- 注意,此时对象中的属性值,可以是确定的样式值,也可以是 vue 的数据变量,
- 因此有些值不能再像
style标签中一样书写,例如50px,以前使用不加引号,现在必须加引号
对象写法关于值的问题
如果使用动态绑定属性 style 里的对象值不加引号, 就会有如下的问题:
<h2 :style="{color:red,font-size:30px}">Hello World</h2>上面的这种写法就会报错, red和30px会被当做变量去Vue data属性中找对应的数据, 但是找不到就报错
正确的写法应该是这样的
<h2 :style="{color:'red',fontSize:'30px'}">Hello World</h2>也能正确显示结果, 但是要注意字符串嵌套问题

对象写法的属性问题:
相信通过刚才的例子,你也发现了,我们发font-size 的写法改为了fontSize.
因为 CSS 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case) 都可以:
因此,在普通的style属性中一下两种写法都可以
<!-- 驼峰式 (camelCase) 写法 ---><h2 style="color:red;fontSize:30px;">Hello World</h2>
<!-- 短横线分隔 (kebab-case ---><h2 style="color:red;font-size:30px;">Hello World</h2>两种处理方法:
- 驼峰式 (camelCase)
- 如果要使用连字符, 就需要添加双引号, 将属性变成字符串的写法
因此动态绑定需要如下写法
<!-- 驼峰式 (camelCase) 写法 ---><h2 :style="{color:'red', fontSize:'30px'}">Hello World</h2>
<!-- 短横线分隔 (kebab-case) 但是要加引号 ---><h2 :style="{color:'red', 'font-size' :'30px'}">Hello World</h2>推荐用驼峰写法, 对象的值也可以是变量
示例代码
<div id="app"> <div :style="{ color: activeColor, fontSize: fontSize + 'px' }">菜鸟教程</div></div>
<script>const app = { data() { return { activeColor: 'red', fontSize: 30 } }}
Vue.createApp(app).mount('#app')</script>浏览器渲染
<div style="color: red; font-size: 30px;">菜鸟教程</div>style 绑定对象(推荐)
代码
<div id="app"> <div :style="styleObject">菜鸟教程</div></div>
<script>const app = { data() { return { styleObject: { color: "red", fontSize: "30px" } } }}
Vue.createApp(app).mount('#app')浏览器渲染
<div style="color: red; font-size: 30px;">菜鸟教程</div>同样的,如果样式对象需要更复杂的逻辑,也可以使用返回样式对象的计算属性。
动态修改样式
代码
<script src="https://unpkg.com/vue@next"></script> <div id="app"> <h2 :style="styleObject">Hello World</h2> <button @click="changColor">点击切换颜色</button> </div>
<script> const App = { data() { return { styleObject: { color: "red", fontSize: "30px" } } }, methods: { changColor() { this.styleObject.color = this.styleObject.color == "red" ? "skyblue" : "red" } } } const app = Vue.createApp(App); app.mount("#app"); </script>浏览器运行效果
原网页中的可执行演示已停用,以下完整保留为静态 HTML 代码。
<script src="https://unpkg.com/vue@next"></script> <div id="app"> <h3 :style="styleObject">Hello World</h3> <button @click="changColor">点击切换颜色</button> </div>
<script> const App = { data() { return { styleObject: { color: "red", fontSize: "30px" } } }, methods: { changColor() { this.styleObject.color = this.styleObject.color == "red" ? "skyblue" : "red" } } } const app = Vue.createApp(App); app.mount("#app"); </script>style 绑定数组
可以扩展对象的用法,给动态属性的值绑定为数组,数组中就可以使用多组样式对象来绑定 CSS 样式。
这些对象会被合并后渲染到同一元素上:
代码
<div id="app"> <div :style="[baseStyles, overridingStyles]">菜鸟教程</div></div>
<script>const app = { data() { return { baseStyles: { color: 'green', fontSize: '30px' }, overridingStyles: { 'font-weight': 'bold' } } }}
Vue.createApp(app).mount('#app')浏览器渲染
<div style="color: green; font-size: 30px; font-weight: bold;">菜鸟教程</div>注意:
当 v-bind:style 使用需要特定前缀的 CSS 属性时,如 transform ,Vue.js 会自动侦测并添加相应的前缀。
自动前缀
当你在 :style 中使用了需要浏览器特殊前缀的 CSS 属性时,Vue 会自动为他们加上相应的前缀。Vue 是在运行时检查该属性是否支持在当前浏览器中使用。如果浏览器不支持某个属性,那么将测试加上各个浏览器特殊前缀,以找到哪一个是被支持的。
多重值
可以为 style 绑定中的 property 提供一个包含多个值的数组,常用于提供多个带前缀的值,例如:
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>这样写只会渲染数组中最后一个被浏览器支持的值。在本例中,如果浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染 display: flex。
💛组件
单个根元素的自定义组件
当你在带有单个根元素的自定义组件上使用 class 属性时,这些 class 将被添加到该元素中。此元素上的现有 class 将不会被覆盖。
<div id="app"> <runoob class="classC classD"></runoob></div>app.component('runoob', { template: '<h1 class="classA classB">I like runoob!</h1>'})浏览器渲染
<h1 class="classA classB classC classD">I like runoob!</h1>带数据绑定,此元素上的现有 class 将不会被覆盖。
<my-component :class="{ active: isActive }"></my-component>渲染(isActive为真)
<p class="active">Hi</p>多个根元素
如果你的组件有多个根元素,你需要定义哪些部分将接收这个类。可以使用 $attrs 组件属性执行此操作:
<script src="https://unpkg.com/vue@next"></script><style>.classA { color: red; font-size:30px;}</style>
<div id="app"> <runoob class="classA"></runoob></div>
<script>const app = Vue.createApp({})
app.component('runoob', { template: ` <p :class="$attrs.class">I like runoob!</p> <span>这是一个子组件</span> `})
app.mount('#app')</script>注意:template 中 ` 是反引号,不是单引号 '。
浏览器渲染
<div id="app"><p class="classA">I like runoob!</p><span>这是一个子组件</span></div>原网页中的可执行演示已停用,以下完整保留为静态 HTML 代码。
<style>.classA { color: red; font-size:30px;}</style>
<div id="qpp"> <runoob class="classA"></runoob></div>
<script>const qpp = Vue.createApp({})
qpp.component('runoob', { template: ` <p :class="$attrs.class">I like runoob!</p> <span>这是一个子组件</span> `})
qpp.mount('#qpp')</script>拓展想象
若是配合 CSS 变量,岂不是有无限可能