1.动态组件
动态组件:顾名思义,动态组件就是可以动态的切换组件的显示
需求:根据不同的状态显示不同的状态
1.1 使用 v-if
或 v-show
切换组件
示例代码如下:
<style>
*{
margin: 0;
padding: 0;
}
li{
list-style: none;
}
#app{
width: 100vw;
height:100vh;
}
.option ul{
display: flex;
position: fixed;
left: 0;
right:0;
bottom:0;
height:50px;
border-top:2px solid #FFCA28;
}
.option ul li{
flex: 1;
text-align:center;
line-height: 50px;
font-size:22px;
color:#fff;
background: #FFCA28;
}
.content{
position: fixed;
top:0;
left:0;
right:0;
bottom: 52px;
background:#C5E1A5;
padding:30px;
}
</style>
</head>
<body>
<div id="app">
<div class="content">
<home v-if = "current == 'Home'"></home>
<my-com v-if = "current == 'MyCom'"></my-com>
<about v-if = "current == 'About'"></about>
</div>
<div class="option">
<ul>
<li @click="handleClick('Home')">Home</li>
<li @click="handleClick('MyCom')">Content</li>
<li @click="handleClick('About')">About</li>
</ul>
</div>
</div>
<script>
let Home= ({
template:`
<h2>我是home组件</h2>
<input type = "text">
`,
})
let MyCom = {
template:`
<h2>Article组件</h2>
`,
}
let About= ({
template:`
<h2>我是About组件</h2>
`,
})
let vm = new Vue({
el:"#app",
data:{
current:"Home"
},
methods:{
handleClick(value){
this.current = value
}
},
components: {
Home,About,MyCom
}
})
</script>
</body>
页面的显示效果如下:
虽然这样可以实现我们想要的效果,但是是非常不友好的做饭,假如我们有很多的组件需要切换,那么就要写很多的v-if
来实现切换.
所以Vue
帮我们提供了动态组件来解决这个问题.
1.2 动态组件的基本用法
在不同的组件之间的切换,动态组件是非常好用且高效的办法.
通过使用保留的 <component>
元素,并对 is
属性进行绑定,我们就可以在同一挂载点切换多个组件,使用动态组件重新写上面的案例
将上面案例中的如下代码:
<home v-if = "current == 'Home'"></home>
<my-com v-if = "current == 'MyCom'"></my-com>
<about v-if = "current == 'About'"></about>
替换为这句代码就可以实现相同的效果:
<component :is="current"></component>
此时的 is
属性的值是通过 v-bind
指令动态绑定到 data
属性中的数据,此时编译后的is
的值是哪一个组件的名字就会显示哪一个组件.
2.keep-alive在动态组件上的使用
当我们在这些组件之间切换的是,有时候就会希望保持某些组件的状态,以此来避免重复渲染带来的问题.
比如说我们当前在登录页面,输入了登录的信息,但是不小心点到了注册页面,当我们返回到登录页面的额时候就会希望保留我们已经输入过的登录信息,就需要用到keep-alive
.
keep-alive
一般用于组件的切换,否则组件在切换时,会频繁的创建和删除组件,不太好,这样也没法在组件切换是保存之前状态.
2.1 不使用keep-alive
如果我们不使用keep-alive
,就会在每次切换组件的时候,先删除旧的组件,然后渲染新的组件.
每个组件也都有自己的生命周期,我们把生命周期 函数添加上看看是不是每次切换组件都是在重新创建和删除组件.看看会先渲染新的组件还是先删除旧的组件???
示例代码如下:
<div id="app">
<div class="content">
<component :is="current"></component>
</div>
<div class="option">
<ul>
<li @click="handleClick('Home')">Home</li>
<li @click="handleClick('MyCom')">Content</li>
<li @click="handleClick('About')">About</li>
</ul>
</div>
</div>
<script>
let Home= ({
template:`
<div>
<h2>我是home组件</h2>
<input type = "text" />
</div>
`,
beforeCreate () {
console.log("Home beforeCreate")
},
created () {
console.log("Home Create")
},
beforeMount () {
console.log("Home beforeMount");
},
mounted () {
console.log("Home mounted");
},
beforeDestroy () {
console.log("Home beforeDestroy");
},
destroyed () {
console.log("Home destroyed");
},
activated(){
// 当前组件处于活跃状态 ,
console.log('activate')
},
deactivated(){
// 当前组件不处于活跃状态, 冻结
console.log("deactivate")
}
})
let MyCom = {
template:`
<h2>Article组件</h2>
`,
beforeCreate () {
console.log("MyCom beforeCreate")
},
created () {
console.log("MyCom Create")
},
beforeMount () {
console.log("MyCom beforeMount");
},
mounted () {
console.log("MyCom mounted");
},
beforeDestroy () {
console.log("MyCom beforeDestroy");
},
destroyed () {
console.log("MyCom destroyed");
}
}
let About= ({
template:`
<h2>我是About组件</h2>
`,
})
let vm = new Vue({
el:"#app",
data:{
current:"Home"
},
methods:{
handleClick(value){
this.current = value
}
},
components: {
Home,About,MyCom
}
})
</script>
我将页面从home
页切换到content
页面,观察一下打印的信息:
通过这些生命周期的钩子函数的打印,我们可以发现:
在切换组件的时候.会在虚拟DOM
已经准备添加时删除旧的组件,然后再渲染新的DOM
元素.
因为每次组件切换都是新创建的组件,都是全新的,那么在组件切换前的组件状态将没发保存.
2.2使用keep-alive
但是在这个案例中,我们更希望那些标签的Home
组件实例能够被在它们第一次被创建的时候缓存下来。为了解决这个问题,我们可以用一个<keep-alive>
元素将其动态组件包裹起来。
将上面示例代码中的如下内容:
<component :is="current"></component>
替换为
<keep-alive exclude="MyCom,About">
<component :is="current"></component>
</keep-alive>
注:exclude
属性中的内容的意思是里面的组件不要被keep-alive
保持组件的状态.
仔细观察上图中vue
显示内容的变换,当我们从 home
切换到 content
或 About
时,home
组件的显示颜色会变浅而不是消失.而 Content
和 About
都会消失.且我们在 home
页面 input
中输入的内容也不会消失. 这就是 keep-alive
的作用,能够保存当前组件的状态.
组件不会被销毁,而是一直会缓存这.
2.3 activated和deactivated
简单介绍:
- activated:被 keep-alive 缓存的组件激活时调用。该钩子在服务器端渲染期间不被调用。
- deactivated:被 keep-alive 缓存的组件停用时调用。该钩子在服务器端渲染期间不被调用。
通过案例来看:
let Home= ({
template:`
<div>
<h2>Home组件</h2>
<input type="text">
</div> `,
activated(){
// 当前组件处于活跃状态 ,
console.log('activate')
},
deactivated(){
// 当前组件不处于活跃状态, 冻结
console.log("deactivate")
}
})
let MyCom = {
template:`
<h2>Article组件</h2>
`,
}
当我们在 home
页面的时候回打印 activated
,如果我们从 home
页面切换到 content
页面时会打印 deactivated
.
即当我们在 home
页面时 home
组件处于活跃状态,当我们切换到其他页面的时候, home
组件处于不活跃状态,即冻结状态.