Vue 2.0的学习笔记:在Vue中使用样式
到目前为止,学习Vue的时候也写了相当的示例,但老实说,这些示例在视觉上并没有什么吸引人的地方。今天我们将学习如何将样式运用到我们的元素中,让事情变得更加有趣。首先我们将通过将内联样式添加到HTML的元素中,其实也就是我们以前所说的内联样式。其实在学习v-bind
的时候,我们已经或多或少的接触了,如何给元素添加内联样式或者绑定类名添加样式。但这可能不够系统,为了更好的学习这方面的知识,这篇文章专门是学习这方面知识而做的笔记。希望对和我一样的初学者有所帮助。
在Vue中使用内联样式
比如说,我们有一个width
和height
都是200px
的div
,我想做的第一件事情就是设置这个元素的背景色为blue
。
<div style="width: 200px; height: 200px;" v-bind:style=""></div>
当v-bind
绑定到style
属性时,表达式可以是对象也可以是数组。先看看对象语法是什么样子。这个对象中的键应该与想要设置的CSS样式相匹配,而值应该是一个表达式,它可以解析为一个值。在这种情况下,对象的key
是background-color
。在JavaScript中,我们需要将键值放在引号内,因为它包含了一个破折号-
。请注意,我将在这里使用单引号,因此不必避免双引号,因为它们会干扰HTML标记。
这就是我想要应用到div
元素的样式的别名,对于值,也可以简单地在单引号中写入,比如blue
。
<div style="width: 200px; height: 200px;" v-bind:style="{ 'background-color': 'blue' }"></div>
我们期望看到一个blue
的正方形。
事实上,这并没有起任何作用,因为我们在模板中直接定义了颜色。如果这就是我们所需要的,那么还不如直接在div
元素的style
属性中添加需要的样式,这样做将更有用。事实上,在Vue中通过v-bind
绑定style
是期望绑定一个动态颜色。让我们创建一个包含颜色的数据属性,并绑定到模板中的这个属性。
let app = new Vue({
el: '#app',
data () {
return {
color: 'blue'
}
}
})
现在我只需要将这个属性的名称作为background-color
的表达式,结果是相同的。
<div style="width: 200px; height: 200px;" v-bind:style="{ 'background-color': color }"></div>
当然,这也不太有用,因为我们在Vue实例中硬编码了color
。但这让我们能做的就是动态改变color
。当我们这么做的时候,你也将会猜到,Vue将自动更新样式,因为我们已经将background-color
绑定到了data
中的color
属性。为了展示这个效果,咱们可以添加一个button
,给这个button
绑定一个click
事件,点击事件监听div
颜色改变。
<div id="app">
<button @click="{{changeColor}}">Click Me (^_^)</button>
<div style="width: 200px; height: 200px;" v-bind:style="{ 'background-color': color }"></div>
</div>
使用Vue的computed
给button
添加了changeColor
。这个方法里侦听了background-color
的改变,使用简单的if
语句,将data
中的color
从blue
转换成red
:
let app = new Vue({
el: '#app',
data () {
return {
color: 'blue'
}
},
computed: {
changeColor: function () {
if (this.color = 'blue') {
this.color = 'red'
} else {
this.color = 'blue'
}
}
}
})
看到的效果如下:
当你点击按钮之后,我们看到div
元素的背景从blue
变成了red
。
上面的示例中,咱们使用的是Vue的
computed
,除了使用computed
还可以使用methods
或者说watch
。
你可能会想到,如果我们在模板中添加更多的属性,就很难读取它。为了解决这个问题,我们可以简单地将对象移到data
中,并在模板中引用该属性,比如我将调用data
中的styles
属性。
将上面的代码稍微清理一下,历为我们将不再需要更改颜色的按钮。
data () {
return {
styles: {
'background-color': 'blue'
}
}
}
有了这个,就可以在模板中通过v-bind
调用styles
:
<div style="width: 200px; height: 200px;" v-bind:style="styles"></div>
你将看到的效果是和前面的示例一样的:
在文章最开始之前,你是否注意到了,在HTML模板中引用了一个style
属性。我们可以将style
属性中运用到的样式,一起放到data
的styles
中:
data () {
return {
styles: {
'background-color': 'blue',
width: '200px',
height: '200px'
}
}
}
<div v-bind:style="styles"></div>
对于简单的例子来说,这一切都很好,但是如果我们需要使用其他数据属性来确定样式呢?也许我们总是想把width
设置为height
的一半。当然,我们可能会偷懒,只是把宽度改变100px
,但这么做很没趣,是吧。由于我们无法从styles
对象中访问其他数据属性,所以我们需要做些别的事情。你可能猜到了,我们可以使用Vue的computed
。因此,让我们将数据属性改为一个计算属性。
let app = new Vue({
el: '#app',
data () {
return {
//
}
},
computed: {
styles: function () {
let height = 200
return {
'background-color': 'blue',
width: (height / 2) + 'px',
height: height + 'px'
}
}
}
})
<div v-bind:style="styles"></div>
现在我们看到的宽度是高度的一半。关键是,如果你的样式不依赖另一个数据属性,或者如果它们使用了计算属性,则可以使用数据属性。
前面也提到过,除了可以使用对象之外,还可以使用数组的样式。这可能有点不太常见,但让我们看看如何做。
如果我们添加一个数组而不是一个对象,那么这个数组实际上应该是一个对象数组,其中每个对象使用的语法和我们刚才看到的一样。重点是你可以重写样式。因此,我添加了一个名为moreStyles
的新数据属性,它通过使用border-radius
给div
添加圆角。
let app = new Vue({
el: '#app',
data () {
return {
moreStyles: {
'border-radius': '5px'
}
}
},
computed: {
styles: function () {
let height = 200
return {
'background-color': 'blue',
width: (height / 2) + 'px',
height: height + 'px'
}
}
}
})
<div v-bind:style="[styles, moreStyles]"></div>
当然,我们可以引用一个由数组组成的数据属性,也可以是一个返回数组的计算属性。
它将两个对象合并在一起,所以说,我们运行代码,你会看到div
仍然有相同的样式,但它现在也有圆角。这是因为VUe将这些对象合并在一起。值得注意的是,数组中的对象优先于它闪之前添加的任何对象。如果我将background-color
在moreStyles
中添加,并设置其值为red
,我们会看到div
的背景色变成了red
。虽然我们已经在第一个对象styles
,也就是computed
中设置的background-color
为blue
。
let app = new Vue({
el: '#app',
data () {
return {
moreStyles: {
'border-radius': '5px',
'background-color': 'red'
}
}
},
computed: {
styles: function () {
let height = 200
return {
'background-color': 'blue',
width: (height / 2) + 'px',
height: height + 'px'
}
}
}
})
有趣的是,Vue会自动地将CSS样式预先修改,以确保浏览器的最大兼容性。这意味着在使用这样的内联样式时,不需要担心使用自动修复程序之类的工具,因为这些工具很难使用内联样式。
上在我们看到的都是在Vue中怎么使用内联样式,其实除了内联样式,还可以使用CSS的class
样式。接下来看看如何在Vue中使用CSS的类样式。
在Vue中使用CSS类的样式
通过前面的学习,我们知道如何通过v-bind
绑定style
属性来添加内联样式,现在我们来看看如何使用类来进行样式美化。虽然使用样式属性是很方便的,有时也很有必要的,但很多时候都是基于元素的class
和id
在外部编写CSS样式才是最佳的方式。
我已经提前准备了一些简单的CSS的类。假设我们有一个shapes
的数组,它可以是一个圆,也可以是一个正方形,而且每个形状都有一些与之相关的通用样式。我们通过在每个形状对象上有一个isRound
属性来区分是圆形还是正方形。有了这个,我们就可以创建一个div
元素,它通过使用v-for
指令来遍历data
中的shapes
数组。在我们决定哪个类应该在div
元素上使用之前,我将把它写出来。
<div id="app">
<div v-for="shape in shapes"></div>
</div>
**注意:**始终给
div
元素添加shape
的类名。
<div id="app">
<div v-for="shape in shapes" class="shape"></div>
</div>
假设shape
有一个默认的样式:
.shape {
width: 150px;
height: 150px;
margin: 10px;
background: #f36;
}
这个时候你看到的效果将是这样:
类似前面所讲的一样,同样可以使用v-bind
绑定style
那样来绑定class
属性:
<div id="app">
<div v-for="shape in shapes" class="shape" v-bind:class="{ }"></div>
</div>
现在,这个对象的语法在class
属性的上下文中略有不同。对象的键应该匹配类名,而值应该是计算而尔值的表达式。如果布尔值为true
,则添加类名,否而类名将不会添加到DOM中。因此,你可以向对象添加类,即使你不知道它们是否将在运行时添加。
我们现在要做的事情是,将有条件添加类名circle
,因此我将输入circle
作为对象的key
。至于表达式,如果isRound
属性在这个对象上是true
,那么就给这个元素添加类名circle
。
<div id="app">
<div v-for="shape in shapes" class="shape" v-bind:class="{ circle: shape.isRound }"></div>
</div>
因此,如果shape
对象上的isRound
属性为true
时则会添加circle
类。如果它是false
,那么这个类就不会被添加到DOM中。
现在我们已经检查了shape
是不是一个圆,但是我们也需要检查它是否是一个正方形,如果是这样,添加适当的类。我们对square
类做同样的操作。
<div id="app">
<div v-for="shape in shapes" class="shape" v-bind:class="{ circle: shape.isRound, square: !shape.isRound }"></div>
</div>
这样,每个div
元素都将包含shape
类名,并且会根据isRound
的值对应的添加circle
或者square
类名。
我们可以根据样式来判断,第一个形状是圆,第二个形状是方形的。所以这一切看起来都很好。
很明显,这段代码在isRound
属性上不太适合超过两个形状的时候,比如我们有三角形的时候。
假设预定好了CSS样式,所以我们只需要把两个类名分配到一个div
,比如指定triangle
和指定三角形方向的类名,它可以是up
、down
、right
、left
。好,现在我们可以清楚地看到,isRound
属性不是最好的,所以去掉它,添加一个更通用的属性。
我们现在可以假设shape
属性的值将匹配给定形状的CSS类。那么如何将这个类应用到div
元素呢?当我们提供一个对象作为类属性的绑定时,我们指定类名作为对象的键(key
),但在这种情况下,我们需要更动态的东西。我们可以使用另一种诘未能来解决这个问题,它允许我们指定一个数组而不是一个对象。这允许我们指定一组表达式,其中每个表达式可以是字符串,也可以是数据属性的名称。
<div id="app">
<div v-for="shape in shapes" v-bind:class="[ ]" class="shape"></div>
</div>
现在添加适当的类就像键入包含类的属性一样简单,在这种情况下,shape
属性在shape
的别名上。
<div id="app">
<div v-for="shape in shapes" v-bind:class="[ shape.shape ]" class="shape"></div>
</div>
let app = new Vue({
el: '#app',
data () {
return {
shapes: [
{
shape: 'circle'
},
{
shape: 'square'
}
]
}
}
})
运行代码将显示圆形和正方形,正如上图所看到的效果。这一次以一种更动态的方式来实现的,看上去也比前面的示例更简单。目前为止一切都很顺利。现在让我们来添加三角形,因此我们需要向shapes
数组中添加一些对象。三角形形状的类名不是我们想要的三角形,我们需要指定一个方向,可以是up
、down
、left
或right
。将给每个方向添加一个三角形。
let app = new Vue({
el: '#app',
data () {
return {
shapes: [
{
shape: 'circle'
},
{
shape: 'square'
},
{
shape: 'triangle',
direction: 'up'
},
{
shape: 'triangle',
direction: 'right'
},
{
shape: 'triangle',
direction: 'down'
},
{
shape: 'triangle',
direction: 'left'
}
]
}
}
})
运行上面的代码,并没有看到我们想要的三角形。对于要显示三角形,我们还需要向类中添加三角形方向的类名。但是,不是所有的形状都有方向,所以我们怎么才能动态地添加方向的类名呢?记住,数组语法允许我们添加表达式,因此可以添加一个简写if
语句来检查当前形状是否有方向属性。因此,如果direction
属性包含一个truthy
值(也就是说不是未定义的),我们将把属性值添加为一个类,否则我们将添加一个空字符串。
<div id="app">
<div v-for="shape in shapes" v-bind:class="[ shape.shape, shape.direction ? shape.direction : '' ]" class="shape"></div>
</div>
现在,我们看到了三角形在页面上渲染出来了。为了向你展示一些我们可以用数组语法做的事情,把示例的功能做得更强一些。假设我们要在加载页面时应用一个动画到某些形状上。
在CSS样式中我已经添加好了一个名为animate
的类名来处理这个效果。现在需要做的就是把这个类添加到元素上,让这个形状动起来。首先需要知道哪些形状会有动画效果,所以在shapes
对象中添加一个animate
的布尔属性。
let app = new Vue({
el: '#app',
data () {
return {
shapes: [
{
shape: 'circle'
},
{
shape: 'square'
},
{
shape: 'triangle',
direction: 'up'
},
{
shape: 'triangle',
direction: 'right',
animate: true
},
{
shape: 'triangle',
direction: 'down'
},
{
shape: 'triangle',
direction: 'left',
animate: true
}
]
}
}
})
现在在data
的shapes
数组里的对象上添加好了animate
属性。现在我们要面对一个小问题。我们如何将animate
类添加到shape
上,这取决于animate
属性的值是否为true
。既然我们知道这个类的名称,我们可以使用另一个简写的if
语句,但我并不想使用这种方法,我想向你展示一种更干净的方法。前面使用对象的时候,它允许我们基于布尔值来切换类。这种方法现在对我们很有用,而且庆幸的是,这也可以用在数组中使用。我们可以做的是,添加一个与前面看到的相同的语法的对象。因为我们想要切换animate
类名,所以将使用它作为对象键,而值是shape
别名上的animate
属性,它包含一个布尔值。如果animate
属性不存在,会视为false
,将不会添加animate
类名。
<div id="app">
<div v-for="shape in shapes" v-bind:class="[ shape.shape, shape.direction ? shape.direction : '', { animate: shape.animate } ]" class="shape"></div>
</div>
当你现在运行代码时,你就可以看到三角形有对应的动画效果,因为animate
类名被添加到了这些形状中。
正如你所看到的,数组语法提供了很多的灵活性,因为你可以混合字符中、数据属性和对象等。
Vue组件的样式
前面看到的是如何在Vue中添加行内样式和通过类名来控制样式。接下来简单的看看Vue组件的样式处理。
得益于Vue-loader,在Vue中可以使用类似于Web Component的组件化写法:
<template>
<!-- 组件模板写在这里 -->
</template>
<script>
// 组件逻辑相关代码写这里
</script>
<style>
/* 组件样式写在这里 */
</style>
在大多数情况下,我们希望组件间定义的样式是相互隔离的。所以我们可以增加scoped
标识。Vue-loader在编译的过程中会为组件每一个元素节点增加scoped
作为属性,同时为所有样式类加上属性选择器scoped
,从而达到隔离的效果。
如果我们是使用Vue-CLI构建Vue项目,其已经内置好了Sass和LESS这样的处理器的配置。如果我们需要的话直接下载两个模块就可以了,而Webpack它会根据lang
属性自动用适当的加载器去处理。
如果需要使用Sass,则安装:
npm i node-sass --save-dev
npm i sass-loader --save-dev
如果需要使用LESS,则安装:
npm i less --save-dev
npm i less-loader --save-dev
在组件中写样式的时候,可以这样处理:
<style lang="sass" scoped>
/* Sass 样式*/
</style>
<style lang="less" scoped>
/* LESS 样式*/
</style>
有关于这方面更详细的介绍,我们可以在学习组件开发的时候再深入的了解。
总结
这篇文章主要学习了如何通过v-bind
给Vue的元素添加内联样式和通过绑定class
来动态改变元素样式。另外简单的介绍了,如何在Vue组件中写样式。其实除了这些方式,还可以像普通的Web开发一样,引用样式文件。但这些都不重要,重要的是要掌握如何在Vue中使用内联样式和动态改变样式。
由于作者是Vue的初学者,如果文章中有不对之处,还请各咱大婶拍正,或者你有更好的建议和想法,欢迎在下面的评论中与我们一起分享。
如需转载,烦请注明出处:https://www.fedev.cn/vue/bind-inline-style-and-class.html