动态组件适用于在不同组件之间进行动态切换。我使用过2种方法来实现:
(1)可以通过 Vue 的 <component> 元素加一个特殊的 is 特性来实现;
(2)通过v-if来进行条件渲染,同样能实现。
下面是2种实现方法的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>动态组件的使用</title>
<style>
*{
margin: 0;
padding: 0;
}
[v-cloak]{ /*防止刷新时闪烁 */
display: none;
}
#app{
margin:100px 200px;
}
button{
width:80px;
height: 50px;
line-height: 50px;
font-size: 20px;
outline: none;
border-radius: 1px;
}
.isActive{
background: #ccc;
}
.tab{
width:600px;
height: 200px;
border:2px solid #ccc;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<h3>方法1:使用v-if来实现组件之间动态切换</h3>
<button
v-for="tab in tabs"
:key="tab"
@click="setCurrentTab(tab)"
:class="{isActive:currentTab === tab}">
{{ tab }}
</button>
<tab-home v-if="currentTab == 'Home'"></tab-home>
<tab-posts v-if="currentTab == 'Posts'"></tab-posts>
<tab-article v-if="currentTab == 'Article'"></tab-article>
<h3 style="margin-top: 50px;">方法二:使用<component is="currentTabComponent"></component>'来实现真正的动态组件切换</h3>
<button
v-for="tab in tabs"
:key="tab"
@click="setCurrentTab(tab)"
:class="{isActive:currentTab === tab}">
{{ tab }}
</button>
<component :is="currentTabComponent"></component>
</div>
<script src="../vue.min.js"></script>
<script>
//定义3个组件----全局注册组件
Vue.component('tab-home',{
template:`
<div class="tab">
Home组件
</div>
`
})
Vue.component('tab-posts',{
template:`
<div class="tab">
Posts组件
</div>
`
})
Vue.component('tab-article',{
template:`
<div class="tab">
Article组件
</div>
`
})
var vm = new Vue({
el:'#app',
data:{
currentTab:'Home',
tabs:['Home','Posts','Article']
},
methods:{
setCurrentTab:function(val){ //设置当前选中的选项卡
this.currentTab = val;
}
},
computed:{
currentTabComponent:function(){
return 'tab-' + this.currentTab.toLowerCase(); //设置当前选中选项卡对应的组件
}
}
})
</script>
</body>
</html>
结论:显然的是,使用Vue保留的元素<component :is="currentTabComponent"></component>更加方便高效。
值得注意的是:在这里注册的组件都是全局注册的,在<component :is="currentTabComponent"></component>中,currentTabComponent表示已全局注册的组件名称。但是currentTabComponent可以支持2种情况:
(1)即上述所说的已注册的组件名称
(2)一个组件的选项对象
第2种情况的使用,如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>动态组件</title>
<style>
*{
margin: 0;
padding: 0;
}
[v-cloak]{
display:none;
}
#app{
margin: 100px 100px;
}
button{
width: 120px;
height: 50px;
font-size: 20px;
line-height: 50px;
border-radius: 1px;
outline: none;
cursor: pointer;
}
.isActive{
background: rgb(182, 179, 179);
}
.tab{
width:600px;
height: 200px;
border:2px solid #ccc;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<button
v-for="tab in tabs"
:key="tab.name"
@click="setCurrentTab(tab)"
:class="{isActive:currentTab.name === tab.name}">
{{tab.name}}
</button>
<!-- 注意与使用组件名称的区别 -->
<component :is="currentTab.component" class="tab"></component>
</div>
<script src="../vue.min.js"></script>
<script>
//定义组件选项对象
var tabs = [
{
name:"Home",
component:{
template:`<div class="tab">Home组件</div>`
}
},
{
name:"Posts",
component:{
template:`<div class="tab">Posts组件</div>`
}
},
{
name:"Article",
component:{
template:`<div class="tab">Article组件</div>`
}
}
];
var vm = new Vue({
el:'#app',
data:{
tabs:tabs,
currentTab:tabs[0]
},
methods:{
setCurrentTab:function(val){
this.currentTab = val;
}
}
})
</script>
</body>
</html>