第5章绑定CSS样式


视频讲解


CSS样式用来决定网页的外观。DOM元素的class属性和style属性都用于设定CSS样式。例如,以下<div>元素的class属性设定字体为红色: 


<style>

.redtext {color: red}

</style>



<div  class="redtext" >Hello</div>


以下<div>元素的style属性设定字体为红色: 


<div  style="color: red" >Hello</div>


以上<div>元素的class属性和style属性的取值是固定的。如果希望设置动态值,那么可以通过Vue的vbind指令为class属性或style属性绑定一个动态值。本章介绍为DOM元素动态绑定CSS样式的方法。
5.1绑定class属性
DOM元素的class属性用来设定一个样式类型。在例程51中,定义了static、redtext和bluetext 3个样式类型。<div>元素的class属性包含了static和redtext这两个样式类型。

例程51original.html



<style>

.static{




width: 100px;

height: 50px;

text-align: center; 

background: yellow 

} 

.redtext {color: red}

.bluetext{color: blue}

</style>



<div id="app">

<div  class="static redtext">Hello</div>

</div>


通过浏览器访问original.html,会看到网页上有一个黄色的矩形框,矩形框中有一个红色的字符串Hello。static样式类型设定了<div>元素的大小和背景色,redtext样式类型设定了字符串Hello的颜色。
如果希望能动态改变网页上字符串Hello的颜色,可以用vbind指令把<div>元素的class属性与一个对象绑定。例如,以下class属性的值是一个对象{redtext:  true}: 


<div  v-bind:class="{redtext: true}">Hello</div>

<!-- 简写为:-->

<div  :class="{redtext: true}">Hello</div>


vbind指令对<div>元素的渲染结果为: 


<div  class="redtext">Hello</div>


以下class属性的值为一个对象{redtext:  false}: 


<div  :class="{redtext: false}">Hello</div>


vbind指令对<div>元素的渲染结果为: 


<div>Hello</div>


由此可见,vbind指令可以动态控制是否使用特定的样式类型。在例程52中,vbind指令把class属性与一个对象{redtext:  isActive}绑定。isActive是一个变量,网页上的“切换字体颜色”按钮使isActive变量的值在true和false之间切换。

例程52redtext.html



<div id="app">

<div  class="static" :class="{ redtext: isActive }">Hello</div>

<button v-on:click="isActive=!isActive">切换字体颜色</button>

</div>



<script>




const vm=Vue.createApp({

data(){

return {isActive: false}

}

}).mount('#app')

</script>


通过浏览器访问redtext.html,会得到如图51所示的网页。


图51redtext.html的网页


一开始,isActive变量的值为初始值false。从图51可以看出,vbind指令对<div>元素的渲染结果为: 


<div  class="static">Hello</div>


在redtext.html的网页上单击“切换字体颜色”按钮,isActive变量的值变为true,这时网页上Hello字符串变成红色。vbind指令对<div>元素的渲染结果为: 


<div  class="static redtext">Hello</div>


在例程53中,vbind指令为<div>元素的class属性绑定的对象为{ redtext:  isActive,bluetext:  !isActive }。
当isActive变量的值为true,<div>元素的class属性的渲染结果为static redtext; 当isActive变量的值为false,<div>元素的class属性的渲染结果为static bluetext。

例程53redbluetext.html



<div id="app">

<div  class="static" 

:class="{ redtext: isActive,bluetext: !isActive }">

Hello

</div>

<button v-on:click="isActive=!isActive">切换字体颜色</button>

</div>



<script>

const vm=Vue.createApp({




data(){

return { 

isActive: false

}

}

}).mount('#app')

</script>


在redbluetext.html的网页上多次单击“切换字体颜色”按钮,会看到网页上的字符串Hello的颜色在红色与蓝色之间多次切换。
5.1.1绑定对象类型的变量
如果与DOM元素的class属性绑定的对象很复杂,会影响组件的模板代码的可读性。为了简化模板代码,可以在组件的data选项中定义一个对象类型的变量,再把DOM元素的class属性与这个变量绑定。
在例程54中,<div>元素的class属性与textColor变量绑定。

例程54classobject.html



<div id="app">

<div  class="static" :class="textColor" >Hello</div>

</div>



<script>

const vm=Vue.createApp({

data(){

return { 

textColor: { redtext: true, bluetext:  false }

}

}

}).mount('#app')

</script>


只要改变textColor变量,就能改变模板中<div class="static" : class="textColor" >元素的样式。
5.1.2绑定计算属性
如果把DOM元素的class属性与一个计算属性绑定,就可以在计算属性的get函数中执行一些逻辑运算,从而动态改变class属性的取值。在例程55中,<div>元素的class属性与textColor计算属性绑定。

例程55classcomputed.html



<div id="app">

<div  class="static" :class="textColor">Hello</div>




<button v-on:click="isActive=!isActive">

切换字体颜色      

</button>

</div>



<script>

const vm=Vue.createApp({

data(){

return { 

isActive: false

}

},

computed:{   //计算属性

textColor(){  

return {redtext:this.isActive,bluetext:!this.isActive } 

} 

}

}).mount('#app')

</script>


在classcomputed.html的网页上多次单击“切换字体颜色”按钮,会看到网页上的字符串Hello的颜色在红色与蓝色之间多次切换。
5.1.3绑定数组
还可以把DOM元素的class属性与一个数组绑定,从而把多个样式类型赋值给class属性。在例程56中,<div>元素的class属性与数组[staticClass,redClass]绑定,这样,<div>元素就同时具有static样式类型和redtext样式类型。

例程56classarray.html



<div id="app">

<div  :class="[staticClass,redClass]">Hello</div>

</div>



<script>

const vm=Vue.createApp({

data(){

return { 

staticClass: 'static',

redClass: 'redtext' 

}

}

}).mount('#app')

</script>


在例程57中,通过“?:”三元表达式决定是否使用redClass变量指定的样式。

例程57dynamicarray.html



<div id="app">

<div  :class="[staticClass, isActive ? redClass : '']">Hello</div>

<!--

<div  :class="[staticClass, {redtext:isActive} ]">Hello</div>

-->

<button v-on:click="isActive=!isActive">切换字体颜色</button>

</div>



<script>

const vm=Vue.createApp({

data(){

return { 

isActive: false,

staticClass: 'static',

redClass: 'redtext' 

}

}

}).mount('#app')

</script>


如果与class属性绑定的数组中包含多个三元表达式,会使得代码比较臃肿,为了简化代码,可以用5.1.1节介绍的{样式类型名: true|false}对象替代三元表达式。例如,可以把dynamicarray.html中的<div>元素改写为: 


<div  :class="[staticClass, {redtext:isActive} ]">Hello</div>


当isActive变量为true,class属性就会包含redtext样式类型; 当isActive变量为false,class属性就不会包含redtext样式类型。
5.1.4为Vue组件绑定CSS样式
Vue组件也具有class属性。在例程58中,定义了一个item组件。在item组件的模板中,<div>元素的class属性的值为static。

例程58component.html



<div id="app">

<item class="redtext"></item>

<item :class="{bluetext: isActive}"></item>

</div>



<script>

const app=Vue.createApp({

data(){

return { isActive: true }

}




})



app.component('item',{

template:'<div class="static">Hello</div> '   //item组件的模板

})

app.mount('#app')

</script>


在component.html的根组件的模板中,加入了两个item组件,它们都设置了class属性,如: 


<div id="app">

<item class="redtext"></item>

<item :class="{bluetext: isActive}"></item>

</div>


对于第一个item组件,其模板的渲染结果为: 


<div class="static redtext">Hello</div>


对于第二个item组件,通过vbind指令把class属性与{bluetext:  isActive}对象绑定,isActive变量的值为true。item组件的模板的渲染结果为: 


<div class="static bluetext">Hello</div>


5.2绑定style属性
DOM元素的style属性可以直接指定具体的CSS样式。例如在以下代码中,<div>元素的style属性指定网页上Hello字符串的颜色为红色,字体大小为17px: 


<div style="color: red ; fontSize: 17px ">Hello</div>


如果通过vbind指令把style属性绑定到一个对象,就可以动态改变style属性的值。以下代码把style属性与对象{color:  redColor,fontSize:  size+'px' }绑定: 


<div  v-bind:style="{ color: redColor, fontSize: size+'px' }">

Hello

</div>



<!-- 简写为 -->

<div  :style="{ color: redColor,fontSize: size+'px' }">

Hello

</div>


只要改变size变量的大小,就能改变网页上Hello字符串的字体大小。
在例程59中,size变量的大小可通过单击“字体变大”按钮改变。

例程59stylebind.html



<div id="app">

<div  :style="{ color: redColor,fontSize: size+'px' }">

Hello

</div>

<button v-on:click="size++">字体变大</button>

</div>



<script>

const vm=Vue.createApp({

data(){

return { 

redColor: 'red',

size:17

}

}

}).mount('#app')

</script>


通过浏览器访问stylebind.html,会得到如图52所示的网页。单击网页上的“字体变大”按钮,会看到网页上的Hello字符串的字体不断变大。


图52stylebind.html的网页


5.2.1绑定对象类型的变量
如果与DOM元素的style属性绑定的对象很复杂,会影响模板代码的可读性。为了简化模板代码,可以在Vue组件的data选项中定义一个对象类型的变量,再把DOM元素的style属性与这个变量绑定。
在例程510中,<div>元素的style属性与styleObject变量绑定。

例程510styleobject.html



<div id="app">

<div :style="styleObject">Hello</div>

</div>



<script>

const vm=Vue.createApp({

data(){

return { 

styleObject: { color: 'red',fontSize: '17px' } 




}

}

}).mount('#app')

</script>


只要改变styleObject变量,就能改变模板中<div : style="styleObject">元素的样式。
5.2.2绑定数组
还可以把DOM元素的style属性与一个数组绑定,从而把多个样式赋值给style属性。在例程511中,<div>元素的style属性与数组[staticStyle,redStyle]绑定,这样,<div>元素就同时具有staticStyle变量和redStyle变量指定的样式。

例程511stylearray.html



<div id="app">

<div :style="[staticStyle, redStyle]">Hello</div>

</div>



<script>

const vm=Vue.createApp({

data(){

return { 

staticStyle: {

width:'100px',

height:'50px',

textAlign:'center',

background: 'yellow' 

},

redStyle: {  color: 'red' }

} 

}

}).mount('#app')

</script>


5.2.3与浏览器兼容
由于每个浏览器对CSS样式的支持程度不一样,因此一个HTML文档的CSS样式可能不被所有的浏览器兼容。vbind指令会识别各个浏览器对CSS样式的支持细节,确保HTML文档的CSS样式能够被当前浏览器正确解析。
vbind指令为CSS样式的兼容主要做了以下两方面的工作。
1. 自动添加前缀
随着CSS样式不断升级,有些新出现的样式属性不被所有浏览器支持。例如,新出现的transform样式属性用于对DOM元素进行旋转、缩放和移动等。针对不同的浏览器,需要为该属性添加相应的内核引擎前缀,从而使浏览器支持该属性。在浏览器IE9中,该属性添加前缀后变为mstransform; 在浏览器Safari和Chrome的一些版本中,该属性添加前缀后变为webkittransform。随着浏览器本身的升级换代,前缀的名称也可能会发生变化。
vbind指令能够根据当前使用的浏览器自动为transform属性添加前缀,保证当前浏览器正确解析transform属性。
2. 自动选择合适的样式属性值
同一个样式属性在不同的浏览器中可能有不同的取值。vbind指令允许把一个数组赋值给样式属性,vbind指令会自动从数组中选择适合当前浏览器的属性值,把它赋值给样式属性。
例程512演示了vbind指令为了确保CSS样式与浏览器兼容所做的工作。

例程512styleprefix.html



<div id="app">

<div :style="styleObject">Hello</div>

<div :style="{display:['-webkit-box','-ms-flexbox','flex']}">

Welcome 

</div>

</div>



<script>

const vm=Vue.createApp({

data(){

return { 

styleObject: {

transform: 'rotate(45deg)',  

width: '100px',

height: '50px',

margin: '50px',

textAlign: 'center', 

background: 'yellow'

}

}

}

}).mount('#app')

</script>


在styleprefix.html中,以下<div>元素的style属性与styleObject变量绑定: 


<div :style="styleObject">Hello</div>


在styleObject变量中设定了transform样式属性,代码如下: 


transform: 'rotate(45deg)'//旋转45度


vbind指令会依据当前浏览器的类型,自动为transform样式属性添加相应的前缀,确保当前浏览器能正确解析transform样式属性。
以下<div>元素的style属性中设定了display样式属性,它的值是一个数组: 


<div :style="{display:['-webkit-box','-ms-flexbox','flex']}">


vbind指令会从数组中选择被当前浏览器支持的最后一个元素。例如,假定当前浏览器支持display属性的值为webkitbox和flex,那么以上<div>元素的渲染结果为: 


<div style="display: flex;">


通过Chrome浏览器访问styleprefix.html,会得到如图53所示的网页。


图53styleprefix.html的网页


从图53可以看出,Chrome浏览器会正确解析styleprefix.html的CSS样式。
5.3范例: 变换表格奇偶行的样式
对于HTML表格,为了制造醒目的视觉效果,可以用不同的颜色标识特定行,如用不同的颜色标识奇数行和偶数行。以下代码通过vbind指令把<tr>元素的class属性与对象{markline :  index % 2 !== 0}绑定: 


<tr v-for="(book, index) in books" 

:class="{markline : index % 2 !== 0}">

…

</tr>


当index变量为偶数,index % 2 !== 0的值为false,markline样式不会被添加到class属性中; 当index变量为奇数,index % 2 !==0的值为true,markline样式会被添加到class属性中。表格中第一行的index变量值为0。
例程513按照上述方式用不同的颜色标识表格中的奇数行与偶数行。

例程513books.html



<style>

table {

border: 1px solid black;

width: 100%;

}

th { height: 50px;  }

th, td {

border-bottom: 1px solid #ddd;

text-align: center;




}

.markline {

background-color: #FFCC66;

}

</style>



<div id = "app">

<table>

<tr> 

<th>序号</th> <th>书名</th> <th>作者</th> <th>出版社</th>

</tr>

<tr v-for="(book, index) in books" 

:class="{markline : index % 2 !== 0}">

<td>{{ index+1 }}</td>

<td>{{ book.title }}</td>

<td>{{ book.author }}</td>

<td>{{ book.publisher }}</td>

</tr>

</table>

</div>



<script>

const vm=Vue.createApp({

data(){

return { 

books: [

{ title: '《精通Vue.js:Web前端开发技术详解》',

author: '孙卫琴',

publisher: '清华大学出版社'},

{ title: '《精通Spring:Java Web开发技术详解》',

author: '孙卫琴',

publisher: '清华大学出版社'},

…

]

}

}

}).mount('#app')

</script>


通过浏览器访问books.html,会得到如图54所示的网页。


图54books.html的网页


5.4小结
本章介绍了通过vbind指令为DOM元素动态绑定CSS样式的方法。vbind指令可以把DOM元素的class属性或style属性与一个对象绑定,例如: 


<div  v-bind:class="{redtext: true}">Hello</div>

<!-- 简写为:-->

<div  :class="{redtext: true}">Hello</div>



<div  v-bind:style="{color: redColor}">Hello</div>

<!-- 简写为:-->

<div  :style="{color: redColor}">


以上{redtext:  true}和{color:  redColor}都是对象。如果要绑定的对象比较复杂,为了简化模板代码,可以在Vue组件的data选项中定义一个对象类型的变量,然后把DOM元素的class属性或style属性与这个变量绑定。例如,以下代码把class属性和style属性分别和textColor变量和styleObject变量绑定: 


<div  :class="textColor" >Hello</div>

<div  :style="styleObject">Hello</div>



//textColor和styleObject变量在Vue组件的data选项中定义

data(){

return { 

textColor: { redtext: true, bluetext:  false },

styleObject: { color: 'red', fontSize: '17px' } 

}

}


还可以把一个数组与class属性或style属性绑定,这样就能包含多个样式。例如,以下class属性和style属性都与数组绑定: 


<div :class="[staticClass,redClass]">Hello</div>

<div :style="[staticStyle,redStyle]">Hello</div>


以上[staticClass,redClass]数组和[staticStyle,redStyle]数组中的staticClass、redClass、staticStyle以及redStyle都是在Vue组件的data选项中定义的变量。
5.5思考题
1. 对于以下代码: 


<div :class="{redtext: true}">Hello</div>



:class使用了()指令的缩写形式。(单选)
A. vmodelB. vbindC. vonD. vshow
2. 对于以下代码: 


<style>

.static{

text-align: center; 

background: yellow 

} 

.redtext {color: red}

</style>



<div class="static" :class="{redtext: isActive}">Hello</div>


当isActive变量为true,<div>元素的class属性的渲染结果是()。(单选)
A. staticB. redtext
C. static redtext: trueD. static redtext
3. textStyle变量的定义如下: 


<script>

const vm=Vue.createApp({

data(){

return { 

textStyle: { color: 'red' } 

}

}

}).mount('#app')

</script>


以下选项()会在网页上用红色字体显示字符串Hello。(多选)
A. <div :style="textStyle">Hello</div>
B. <div :style="{textStyle: true}">Hello</div>
C. <div :style="[textStyle]">Hello</div>
D. <div :class="{textStyle: true}">Hello</div>
4. bluetext样式的定义如下: 


<style>

.bluetext {color: blue}

</style>


以下选项()会在网页上用蓝色字体显示字符串Hello。(多选)
A. <div :style="bluetext">Hello</div>
B. <div class="bluetext">Hello</div>
C. <div :class="[bluetext]">Hello</div>
D. <div :class="{bluetext: true}">Hello</div>
5. 对于以下代码: 


<style>

.redtext {color: red}

</style>



<div id="app">

<li  v-for="n in 4" :class="{redtext: n<=2}">{{n}}</li>

</div>


在网页上会看到()。(多选)
A. 网页上输出数字1、2、3、4
B. 所有的数字为黑色字体
C. 所有的数字为红色字体
D. 数字1和2为红色字体