动态组件 —— 2种方式实现动态组件的切换

动态组件适用于在不同组件之间进行动态切换。我使用过2种方法来实现:

(1)可以通过 Vue 的 <component> 元素加一个特殊的 is 特性来实现;

(2)通过v-if来进行条件渲染,同样能实现。

下面是2种实现方法的代码:

  1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4     <meta charset="UTF-8">
  5     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6     <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7     <title>动态组件的使用</title>
  8     <style>
  9         *{
 10             margin: 0;
 11             padding: 0;
 12         }
 13          [v-cloak]{   /*防止刷新时闪烁 */
 14             display: none;
 15         }
 16         #app{
 17             margin:100px 200px;
 18         }
 19         button{
 20             width:80px;
 21             height: 50px;
 22             line-height: 50px;
 23             font-size: 20px;
 24             outline: none;
 25             border-radius: 1px;
 26         }
 27         .isActive{
 28             background: #ccc;
 29         }
 30         .tab{
 31             width:600px;
 32             height: 200px;
 33             border:2px solid #ccc;
 34         }
 35     </style>
 36 </head>
 37 <body>
 38     <div id="app" v-cloak>
 39         <h3>方法1:使用v-if来实现组件之间动态切换</h3>
 40         <button 
 41             v-for="tab in tabs" 
 42             :key="tab" 
 43             @click="setCurrentTab(tab)" 
 44             :class="{isActive:currentTab === tab}">
 45             {{ tab }}
 46         </button>
 47         <tab-home v-if="currentTab == 'Home'"></tab-home>
 48         <tab-posts v-if="currentTab == 'Posts'"></tab-posts>
 49         <tab-article v-if="currentTab == 'Article'"></tab-article>
 50 
 51         <h3 style="margin-top: 50px;">方法二:使用&ltcomponent  is="currentTabComponent"&gt&lt/component&gt'来实现真正的动态组件切换</h3>
 52         <button 
 53             v-for="tab in tabs" 
 54             :key="tab" 
 55             @click="setCurrentTab(tab)" 
 56             :class="{isActive:currentTab === tab}">
 57             {{ tab }}
 58         </button>
 59         <component :is="currentTabComponent"></component>
 60     </div>
 61     <script src="../vue.min.js"></script>
 62     <script>
 63         //定义3个组件----全局注册组件
 64         Vue.component('tab-home',{
 65             template:`
 66                 <div class="tab">
 67                    Home组件
 68                 </div>
 69             `
 70         })
 71         Vue.component('tab-posts',{   
 72             template:`
 73                 <div class="tab">
 74                     Posts组件
 75                 </div>
 76             `
 77         })
 78         Vue.component('tab-article',{
 79             template:`
 80                 <div class="tab">
 81                     Article组件
 82                 </div>
 83             `
 84         })
 85         var vm = new Vue({
 86             el:'#app',
 87             data:{
 88                 currentTab:'Home',
 89                 tabs:['Home','Posts','Article']
 90             },
 91             methods:{
 92                 setCurrentTab:function(val){  //设置当前选中的选项卡
 93                     this.currentTab = val;
 94                 }
 95             },
 96             computed:{
 97                 currentTabComponent:function(){
 98                     return 'tab-' + this.currentTab.toLowerCase();  //设置当前选中选项卡对应的组件
 99                 }
100             }
101         })
102     </script>
103 </body>
104 </html>

结论:显然的是,使用Vue保留的元素<component :is="currentTabComponent"></component>更加方便高效

值得注意的是:在这里注册的组件都是全局注册的,在<component :is="currentTabComponent"></component>中,currentTabComponent表示已全局注册的组件名称。但是currentTabComponent可以支持2种情况:

(1)即上述所说的已注册的组件名称

(2)一个组件的选项对象

第(2)种情况的使用,如下所示:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta name="viewport" content="width=device-width, initial-scale=1.0">
 6     <meta http-equiv="X-UA-Compatible" content="ie=edge">
 7     <title>动态组件</title>
 8     <style>
 9         *{
10             margin: 0;
11             padding: 0;
12         }
13         [v-cloak]{
14             display:none;
15         }
16         #app{
17             margin: 100px 100px;
18         }
19         button{
20             width: 120px;
21             height: 50px;
22             font-size: 20px;
23             line-height: 50px;
24             border-radius: 1px;
25             outline: none;
26             cursor: pointer;
27         }
28         .isActive{
29             background: rgb(182, 179, 179);
30         }
31         .tab{
32             width:600px;
33             height: 200px;
34             border:2px solid #ccc;
35         }
36        
37     </style>
38 </head>
39 <body>
40     <div id="app" v-cloak>
41         <button 
42             v-for="tab in tabs" 
43             :key="tab.name" 
44             @click="setCurrentTab(tab)"
45             :class="{isActive:currentTab.name === tab.name}">
46             {{tab.name}}
47         </button>
48         <!-- 注意与使用组件名称的区别 -->
49         <component :is="currentTab.component" class="tab"></component>  
50     </div>
51     <script src="../vue.min.js"></script>
52     <script>
53         //定义组件选项对象
54         var tabs = [
55             {
56                 name:"Home",
57                 component:{
58                     template:`<div class="tab">Home组件</div>`
59                 }
60             },
61             {
62                 name:"Posts",
63                 component:{
64                     template:`<div class="tab">Posts组件</div>`
65                 }
66             },
67             {
68                 name:"Article",
69                 component:{
70                     template:`<div class="tab">Article组件</div>`
71                 }
72             }
73         ];
74         var vm = new Vue({
75             el:'#app',
76             data:{
77                 tabs:tabs,
78                 currentTab:tabs[0]
79             },
80             methods:{
81                 setCurrentTab:function(val){
82                     this.currentTab = val;
83                 }
84             }
85         })
86     </script>
87 </body>
88 </html>
原文地址:https://www.cnblogs.com/sherryStudy/p/dynamic_component.html