首页 > 其他 > 详细

[Vue学习] 实现Tab选项卡效果, 动态增删Tab, 内容支持动态组件

时间:2021-04-23 00:19:10      阅读:136      评论:0      收藏:0      [点我收藏+]

最近学习了一下Vue, 尝试实现一个自定义Tab组件, 效果如下:

支持动态添加tab项, 内容支持放入动态组件

效果图:

技术分享图片

 

 

 

目录结构:

1. 使用vue-cli创建脚手架项目
2. 在components中创建C1,C2,C3,MyTab四个自定义组件

技术分享图片

 

 

 

package.json

技术分享图片
 1 {
 2   "name": "hello",
 3   "version": "0.1.0",
 4   "private": true,
 5   "scripts": {
 6     "serve": "vue-cli-service serve",
 7     "build": "vue-cli-service build",
 8     "lint": "vue-cli-service lint"
 9   },
10   "dependencies": {
11     "core-js": "^3.6.5",
12     "vue": "^2.6.11"
13   },
14   "devDependencies": {
15     "@vue/cli-plugin-babel": "~4.5.0",
16     "@vue/cli-plugin-eslint": "~4.5.0",
17     "@vue/cli-service": "~4.5.0",
18     "babel-eslint": "^10.1.0",
19     "eslint": "^6.7.2",
20     "eslint-plugin-vue": "^6.2.2",
21     "vue-template-compiler": "^2.6.11"
22   },
23   "eslintConfig": {
24     "root": true,
25     "env": {
26       "node": true
27     },
28     "extends": [
29       "plugin:vue/essential",
30       "eslint:recommended"
31     ],
32     "parserOptions": {
33       "parser": "babel-eslint"
34     },
35     "rules": {}
36   },
37   "browserslist": [
38     "> 1%",
39     "last 2 versions",
40     "not dead"
41   ]
42 }
package.json

 

MyTab.vue

技术分享图片
  1 <script>
  2 export default {
  3   components: {},
  4   props: {
  5     tabs: {
  6       type: Array,
  7       required: true,
  8       default: function name() {
  9         return []
 10       },
 11     },
 12     currentTab: {
 13       type: String,
 14       required: true,
 15     },
 16   },
 17   render: function(h) {
 18     var self = this
 19     return h(
 20       "div", // 标签名称
 21       {
 22         class: "tab-container",
 23       },
 24       [
 25         h(
 26           "ol",
 27           { class: "title" },
 28           self.tabs.map(function name(t) {
 29             return h(
 30               "li",
 31               {
 32                 class: {
 33                   active: self.isActive(t),
 34                 },
 35                 on: {
 36                   click: function name() {
 37                     self.$emit("tabChange", t.title)
 38                   },
 39                 },
 40               },
 41               t.title
 42             )
 43           })
 44         ),
 45         h(
 46           "ol",
 47           { class: "content" },
 48           self.tabs
 49             .filter((t) => {
 50               return self.isActive(t)
 51             })
 52             .map(function name(t) {
 53               return h("li", [h(t.com, { props: t.props })])
 54             })
 55         ),
 56       ]
 57     )
 58   },
 59   methods: {
 60     isActive(tab) {
 61       var cur = this.currentTab
 62       if (cur == "") {
 63         cur = this.tabs[0].title
 64       }
 65       return cur == tab.title
 66     },
 67   },
 68   computed: {},
 69 }
 70 </script>
 71 <style scoped>
 72 ol,
 73 li {
 74   padding: 0;
 75   margin: 0;
 76   list-style: none;
 77 }
 78 
 79 .tab-container {
 80   border: solid 0px #f60;
 81   width: 400px;
 82 }
 83 
 84 .tab-container .title li {
 85   padding: 5px 10px;
 86   background-color: cadetblue;
 87   display: inline-block;
 88   margin: 0 2px 1px 0;
 89   color: #fff;
 90   cursor: pointer;
 91 }
 92 
 93 .tab-container .title li:hover {
 94   background-color: rgb(72, 142, 145);
 95 }
 96 
 97 .tab-container .title li.active {
 98   background-color: rgb(43, 105, 107);
 99 }
100 
101 .tab-container .content li {
102   padding: 5px 10px;
103   background-color: rgb(195, 253, 255);
104   border: solid 2px rgb(51, 141, 148);
105 }
106 </style>
MyTab.vue

 

C1.vue

技术分享图片
 1 <template>
 2   <p>{{ content }}</p>
 3 </template>
 4 <script>
 5 export default {
 6   props: {
 7     content: {
 8       type: String,
 9       default: "none",
10     },
11   },
12   data() {
13     return {}
14   },
15 }
16 </script>
17 <style scoped>
18 ol li {
19   border: solid 1px #abc;
20   padding: 5px 10px;
21 }
22 </style>
C1.vue

 

C2.vue

技术分享图片
 1 <template>
 2   <ol>
 3     <li v-for="tr in list" :key="tr">{{ tr }}</li>
 4   </ol>
 5 </template>
 6 <script>
 7 export default {
 8   props: ["list"],
 9   data1() {
10     return {
11       list: [1, 2, 3, 4, 5, 6],
12     }
13   },
14 }
15 </script>
16 <style scoped>
17 ol li {
18   border: solid 1px #c0c0c0;
19   margin: 2px;
20   padding: 5px 10px;
21 }
22 </style>
C2.vue

 

C3.vue

技术分享图片
 1 <template>
 2   <table>
 3     <tr v-for="(tr, idx) in table" :key="tr[0] + ‘_‘ + idx">
 4       <td v-for="(td, idx2) in tr" :key="td + ‘_‘ + idx + ‘_‘ + idx2">{{ td }}</td>
 5     </tr>
 6   </table>
 7 </template>
 8 <script>
 9 export default {
10   props: ["table"],
11   data1() {
12     return {
13       table: [
14         [1, 2, 3, 4, 5, 6],
15         [2, 4, 5, 6, 7, 8],
16         [3, 4, 5, 6, 7, 8],
17       ],
18     }
19   },
20 }
21 </script>
22 <style scoped>
23 table {
24   border: solid 1px #c0c0c0;
25 }
26 
27 table tr td {
28   padding: 5px 10px;
29   border: solid 1px #c0c0c0;
30 }
31 </style>
C3.vue

 

App.vue

技术分享图片
 1 <template>
 2   <div id="app">
 3     <div class="opt">
 4       <button @click="tabAdd">AddTab</button>
 5       <button @click="tabRemove">RemoveTab</button>
 6       <button>{{ index }}</button>
 7     </div>
 8 
 9     <MyTab :tabs="tabs" v-on:tabChange="tabChange" :currentTab="currentTab"> </MyTab>
10   </div>
11 </template>
12 
13 <script>
14 //import HelloWorld from ‘./components/HelloWorld.vue‘
15 import MyTab from "./components/MyTab.vue"
16 
17 export default {
18   name: "App",
19   components: { MyTab },
20   data() {
21     return {
22       index: 3,
23       currentTab: "textTab",
24       tabs: [
25         {
26           title: "textTab",
27           com: this.$Com("C1"),
28           props: {
29             content: "一段文字而已..",
30           },
31         },
32         {
33           title: "listTab",
34           com: this.$Com("C2"),
35           props: {
36             list: [1, 2, 3, 4, 5, 6],
37           },
38         },
39         {
40           title: "tableTab",
41           com: this.$Com("C3"),
42           props: {
43             table: [
44               [1, 2, 3, 4, 5, 6],
45               [2, 4, 5, 6, 7, 8],
46               [3, 4, 5, 6, 7, 8],
47             ],
48           },
49         },
50       ],
51     }
52   },
53   methods: {
54     tabAdd() {
55       this.tabs.push({
56         title: "tableTab" + this.index++,
57         com: this.$Com("C3"),
58         props: {
59           table: [
60             [1 + this.index, 2, 3, 4, 5, 6],
61             [7 + this.index, 8, 9, 10, 11, 12],
62           ],
63         },
64       })
65     },
66     tabRemove() {
67       if (this.index > 3) {
68         this.tabs.splice(this.tabs.length - 1, 1)
69         this.index--
70         this.currentTab = this.tabs[0].title
71       }
72     },
73     tabChange(currentTab) {
74       this.currentTab = currentTab
75     },
76   },
77 }
78 </script>
79 
80 <style>
81 #app {
82   font-family: Avenir, Helvetica, Arial, sans-serif;
83   -webkit-font-smoothing: antialiased;
84   -moz-osx-font-smoothing: grayscale;
85   color: #2c3e50;
86   margin: 60px;
87   font-size: 14px;
88 }
89 
90 .opt {
91   margin: 10px 0;
92 }
93 .opt button {
94   margin-right: 5px;
95 }
96 </style>
App.vue

 

main.js

技术分享图片
 1 import Vue from "vue"
 2 import App from "./App.vue"
 3 
 4 Vue.config.productionTip = false
 5 
 6 Vue.prototype.$Com = function(fileName) {
 7   return Vue.component(fileName, () => import("./components/" + fileName + ".vue"))
 8 }
 9 
10 new Vue({
11   render: (h) => h(App),
12 }).$mount("#app")
main.js

 

参考1: https://cn.vuejs.org/v2/guide/components-dynamic-async.html
参考2: https://cn.vuejs.org/v2/guide/render-function.html

 

[Vue学习] 实现Tab选项卡效果, 动态增删Tab, 内容支持动态组件

原文:https://www.cnblogs.com/sanshizi/p/14691163.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!