第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的vbind指令为class属性或style属性绑定一个动态值。本章介绍为DOM元素动态绑定CSS样式的方法。 5.1绑定class属性 DOM元素的class属性用来设定一个样式类型。在例程51中,定义了static、redtext和bluetext 3个样式类型。<div>元素的class属性包含了static和redtext这两个样式类型。 例程51original.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的颜色,可以用vbind指令把<div>元素的class属性与一个对象绑定。例如,以下class属性的值是一个对象{redtext: true}: <div v-bind:class="{redtext: true}">Hello</div> <!-- 简写为:--> <div :class="{redtext: true}">Hello</div> vbind指令对<div>元素的渲染结果为: <div class="redtext">Hello</div> 以下class属性的值为一个对象{redtext: false}: <div :class="{redtext: false}">Hello</div> vbind指令对<div>元素的渲染结果为: <div>Hello</div> 由此可见,vbind指令可以动态控制是否使用特定的样式类型。在例程52中,vbind指令把class属性与一个对象{redtext: isActive}绑定。isActive是一个变量,网页上的“切换字体颜色”按钮使isActive变量的值在true和false之间切换。 例程52redtext.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,会得到如图51所示的网页。 图51redtext.html的网页 一开始,isActive变量的值为初始值false。从图51可以看出,vbind指令对<div>元素的渲染结果为: <div class="static">Hello</div> 在redtext.html的网页上单击“切换字体颜色”按钮,isActive变量的值变为true,这时网页上Hello字符串变成红色。vbind指令对<div>元素的渲染结果为: <div class="static redtext">Hello</div> 在例程53中,vbind指令为<div>元素的class属性绑定的对象为{ redtext: isActive,bluetext: !isActive }。 当isActive变量的值为true,<div>元素的class属性的渲染结果为static redtext; 当isActive变量的值为false,<div>元素的class属性的渲染结果为static bluetext。 例程53redbluetext.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属性与这个变量绑定。 在例程54中,<div>元素的class属性与textColor变量绑定。 例程54classobject.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属性的取值。在例程55中,<div>元素的class属性与textColor计算属性绑定。 例程55classcomputed.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属性。在例程56中,<div>元素的class属性与数组[staticClass,redClass]绑定,这样,<div>元素就同时具有static样式类型和redtext样式类型。 例程56classarray.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> 在例程57中,通过“?:”三元表达式决定是否使用redClass变量指定的样式。 例程57dynamicarray.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属性。在例程58中,定义了一个item组件。在item组件的模板中,<div>元素的class属性的值为static。 例程58component.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组件,通过vbind指令把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> 如果通过vbind指令把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字符串的字体大小。 在例程59中,size变量的大小可通过单击“字体变大”按钮改变。 例程59stylebind.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,会得到如图52所示的网页。单击网页上的“字体变大”按钮,会看到网页上的Hello字符串的字体不断变大。 图52stylebind.html的网页 5.2.1绑定对象类型的变量 如果与DOM元素的style属性绑定的对象很复杂,会影响模板代码的可读性。为了简化模板代码,可以在Vue组件的data选项中定义一个对象类型的变量,再把DOM元素的style属性与这个变量绑定。 在例程510中,<div>元素的style属性与styleObject变量绑定。 例程510styleobject.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属性。在例程511中,<div>元素的style属性与数组[staticStyle,redStyle]绑定,这样,<div>元素就同时具有staticStyle变量和redStyle变量指定的样式。 例程511stylearray.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样式可能不被所有的浏览器兼容。vbind指令会识别各个浏览器对CSS样式的支持细节,确保HTML文档的CSS样式能够被当前浏览器正确解析。 vbind指令为CSS样式的兼容主要做了以下两方面的工作。 1. 自动添加前缀 随着CSS样式不断升级,有些新出现的样式属性不被所有浏览器支持。例如,新出现的transform样式属性用于对DOM元素进行旋转、缩放和移动等。针对不同的浏览器,需要为该属性添加相应的内核引擎前缀,从而使浏览器支持该属性。在浏览器IE9中,该属性添加前缀后变为mstransform; 在浏览器Safari和Chrome的一些版本中,该属性添加前缀后变为webkittransform。随着浏览器本身的升级换代,前缀的名称也可能会发生变化。 vbind指令能够根据当前使用的浏览器自动为transform属性添加前缀,保证当前浏览器正确解析transform属性。 2. 自动选择合适的样式属性值 同一个样式属性在不同的浏览器中可能有不同的取值。vbind指令允许把一个数组赋值给样式属性,vbind指令会自动从数组中选择适合当前浏览器的属性值,把它赋值给样式属性。 例程512演示了vbind指令为了确保CSS样式与浏览器兼容所做的工作。 例程512styleprefix.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度 vbind指令会依据当前浏览器的类型,自动为transform样式属性添加相应的前缀,确保当前浏览器能正确解析transform样式属性。 以下<div>元素的style属性中设定了display样式属性,它的值是一个数组: <div :style="{display:['-webkit-box','-ms-flexbox','flex']}"> vbind指令会从数组中选择被当前浏览器支持的最后一个元素。例如,假定当前浏览器支持display属性的值为webkitbox和flex,那么以上<div>元素的渲染结果为: <div style="display: flex;"> 通过Chrome浏览器访问styleprefix.html,会得到如图53所示的网页。 图53styleprefix.html的网页 从图53可以看出,Chrome浏览器会正确解析styleprefix.html的CSS样式。 5.3范例: 变换表格奇偶行的样式 对于HTML表格,为了制造醒目的视觉效果,可以用不同的颜色标识特定行,如用不同的颜色标识奇数行和偶数行。以下代码通过vbind指令把<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。 例程513按照上述方式用不同的颜色标识表格中的奇数行与偶数行。 例程513books.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,会得到如图54所示的网页。 图54books.html的网页 5.4小结 本章介绍了通过vbind指令为DOM元素动态绑定CSS样式的方法。vbind指令可以把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. vmodelB. vbindC. vonD. vshow 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为红色字体