html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="style.css"> <title>Title</title> </head> <body> <div id="app"> <tabs v-model="activeKey"> <pane label="图片"> 我是图片内容... </pane> <pane label="视频"> 我是视频内容... </pane> <pane label="音乐"> 我是音乐内容... </pane> <pane label="文章"> 我是文章内容... </pane> </tabs> </div> <script src="https://unpkg.com/vue/dist/vue.min.js"></script> <script src="pane.js"></script> <script src="tabs.js"></script> <script> var app = new Vue({ el: '#app', data: { activeKey: '0' } }) </script> </body> </html>
css:
[v-cloak] { display: none; } .tabs { font-size: 14px; color:#657180; } .tabs-bar:after{ content:''; display: block; width: 100%; height: 1px; background: #d7dde4; margin-top:-1px; } .tabs-tab { display: inline-block; padding: 4px 16px; margin-right: 6px; background: #ffffff; border: 1px solid #d7dde4; cursor: pointer; position: relative; } .tabs-tab-active { color: #3399ff; border-top: 1px solid #3399ff; border-bottom: 1px solid #ffffff; } .tabs-tab-active:before { content: ''; display: block; height: 1px; background: #3399ff; position: absolute; top: 0; left: 0; right: 0; } .tabs-content { padding: 8px 0; }
pane.js:
Vue.component('pane',{ name: 'pane', template: '<div class="pane" v-show="show"> <slot></slot> </div>', props: { label: { type: String, default: '' } }, data: function () { return { show: true } }, methods: { updateNav: function () { this.$parent.updateNav(); } }, watch: { label: function () { this.updateNav(); } }, mounted: function () { this.updateNav(); } })
tabs.js:
Vue.component('tabs',{ template: '<div class="tabs"> <div class="tabs-bar"> <div v-for="(label,index) in navList" :class="tabCls(index)" @click="handleChange(index)"> {{label}} </div> </div> <div class="tabs-content"> <slot></slot> </div> </div>', props: { value: { type: String } }, data: function () { return { navList: [], currentValue: this.value } }, methods: { tabCls: function (index) { return [ 'tabs-tab', { 'tabs-tab-active':index == this.currentValue } ] }, getTabs: function () { return this.$children.filter(function (t) { return t.$options.name === 'pane'; }); }, updateNav: function () { this.navList = []; var _this = this; this.getTabs().forEach(function (t) { _this.navList.push(t.label); }) this.updateStatus(); }, updateStatus: function () { var _this = this; this.getTabs().forEach(function (t,i) { t.show = i == _this.currentValue; }) }, handleChange: function (index) { this.currentValue = index; this.$emit('input',index); } }, watch: { currentValue: function () { this.updateStatus(); }, value: function (val) { this.currentValue = val; } } })
效果图: