Appearance
Vue中的样式绑定和生命周期
学习目标
- 【掌握】Vue中的Class样式绑定
- 【掌握】Vue中的Style样式绑定
- 【掌握】Vue的生命周期的概念和使用
- 【掌握】Vue的事件修饰符
- 【掌握】Vue的属性修饰符
操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是属性,所以我们可以用 v-bind
处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 v-bind
用于 class
和 style
时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。
1.Vue中的Class样式绑定
先来学习如何给元素动态绑定class,在Vue中提供了2种写法。
1.1 对象写法
在对象写法中,根据每个样式属性的布尔值真假来决定是否将这个样式作用到元素上。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.color1{
color:red
}
.color2{
color: blue;
}
</style>
</head>
<body>
<div id="app">
<h1 :class="{color1:red,color2:blue}">这是一个标题</h1>
<button @click="toggleColor">切换颜色</button>
</div>
<script src="/vue.js"></script>
<script>
new Vue({
el:"#app",
data() {
return {
red:true,
blue:false
}
},
methods: {
toggleColor(){
this.red=!this.red
this.blue=!this.blue
}
},
})
</script>
</body>
</html>
你可以在对象中传入更多字段来动态切换多个 class。此外,v-bind:class
指令也可以与普通的 class属性共存,例如:
html
<h1 :class="{color1:red,color2:blue}" class='bgc'>这是一个标题</h1>
1.2 数组写法
我们还可以把一个数组传给 v-bind:class
,以应用一个 class 列表:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.color{
color:red
}
.bgc{
background-color: blue;
}
</style>
</head>
<body>
<div id="app">
<h1 :class="[color,bgc]">这是一个标题</h1>
</div>
<script src="/vue.js"></script>
<script>
new Vue({
el:"#app",
data() {
return {
color:'color',
bgc:'bgc'
}
},
})
</script>
</body>
</html>
2.Vue中的Style样式绑定
动态地绑定内联样式也是常见的操作,一起来学习如何动态的绑定style内联样式,和Class一样,Vue也提供了对象写法和数组写法。
2.1 对象写法
v-bind:style
的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:
示例中通过点击按钮来实现增大h1标题字体的方法,此时可以将fontSize属性对应的值设置为一个动态属性,然后在点击事件的回调中递增这个属性。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h1 :style="{fontSize:fz+'px'}">这是一个标题</h1>
<button @click="fz++">放大标题</button>
</div>
<script src="/vue.js"></script>
<script>
new Vue({
el:"#app",
data() {
return {
fz:30
}
},
})
</script>
</body>
</html>
2.2 数组写法
v-bind:style
的数组语法可以将多个样式对象应用到同一个元素上:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h1 :style="[style1,style2]">这是一个标题</h1>
</div>
<script src="/vue.js"></script>
<script>
new Vue({
el:"#app",
data() {
return {
style1:{
color:"red"
},
style2:{
backgroundColor:'blue'
}
}
},
})
</script>
</body>
</html>
3.Vue中的生命周期
3.1 生命周期的概念
每个 Vue 实例(包括vm根示例和组件实例)在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
我们书写一个示例来感受一下生命周期:
就以刚才写过的示例为例(h1标题字体变大),通过点击按钮能够实现字体变大,现在希望是页面加载后字体自动变大,不需要手动点击。
那应该如何实现呢,现在的问题就在于之前控制fz递增的逻辑应该放到什么地方中去,可以放到mounted
这个生命周期函数中。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<h1 :style="{fontSize:fz+'px'}">这是一个标题</h1>
</div>
<script src="/vue.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
fz: 30,
}
},
//mounted是生命周期函数的名称,它会在Vue示例挂载完成后自动调用
mounted() {
setInterval(() => {
if (this.fz >= 50) {
return
}
this.fz++
}, 200)
},
})
</script>
</body>
</html>
3.2 常见生命周期
在Vue实例从创建到销毁的过程中,常见的生命周期可以参考如下图示(你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。):
常见的生命周期一共有8个,对应的Vue实例的不同阶段。
- beforeCreate 在实例初始化之后,进行数据侦听和事件/侦听器的配置之前同步调用。
- created 在实例创建完成后被立即同步调用。在这一步中,实例已完成对选项的处理,意味着以下内容已被配置完毕:数据侦听、计算属性、方法、事件/侦听器的回调函数。然而,挂载阶段还没开始,无法进行DOM操作。
- beforeMount 在挂载开始之前被调用:相关的
render
函数首次被调用。 - mounted 实例被挂载后调用,这时
el
被新创建的vm.$el
替换了。如果根实例挂载到了一个文档内的元素上,当mounted
被调用时vm.$el
也在文档内。 - beforeUpdate 在数据发生改变后,DOM 被更新之前被调用。这里适合在现有 DOM 将要被更新之前访问它,比如移除手动添加的事件监听器。
- updated 在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用。当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。
- beforeDestroy 实例销毁之前调用。在这一步,实例仍然完全可用。
- destroyed 实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。
在实际工作开发中,我们常用的生命周期函数一般就只有2-3个:
- created 在这个钩子中我们可以进行数据请求
- mounted 在这个钩子中我们也可以进行数据请求(和created效果一致)和DOM操作
- beforeDestroy 在这个钩子中我们可以销毁定时器和一些全局事件的绑定。
其他生命周期钩子几乎不会被实际应用到,当然还有几个生命周期钩子会在一些特定场景触发,后续再介绍。
4.Vue中的事件修饰符
在事件处理程序中调用 event.preventDefault()
或 event.stopPropagation()
是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。为了解决这个问题,Vue.js 为 v-on
提供了事件修饰符,修饰符是由点开头的指令后缀来表示的。
4.1 .stop
.stop修饰符可以阻止事件的冒泡行为,等同于event.stopPropagation()
html
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
4.2 .prevent
.prevent修饰符可以阻止事件的默认行为,等同于event.preventDefault()
html
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
修饰符还支持链式书写
html
<!-- 修饰符可以链接调用 -->
<a v-on:click.stop.prevent="doThat"></a>
4.3 .self
.self修饰符 只当在 event.target 是当前元素自身时触发处理函数
html
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
4.4 .once
.once 修饰符 绑定的事件只会触发一次
html
<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
4.5 .capture
.capture修饰符 开启事件的捕获模式
html
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
5.Vue中的属性修饰符
除开刚才介绍的事件修饰符,还有一类修饰符也是比较常用的,是用在v-model
指令上的属性修饰符。
5.1 .lazy
在默认情况下,v-model
在每次 input
事件触发后将输入框的值与数据进行同步,你可以添加 lazy
修饰符,从而转为在 change
事件_之后_进行同步。
html
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg">
5.2 .number
如果想自动将用户的输入值转为数值类型,可以给 v-model
添加 number
修饰符。
html
<input v-model.number="age" type="number">
5.2 .trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model
添加 trim
修饰符
html
<input v-model.trim="msg">
在Vue中还有一些键盘修饰符,系统修饰符,使用场景相对更少,同学们可以在官方文档查阅具体的内容。