基於Vue開發的tab切換組件

github地址:https://github.com/MengFangui/VueTabSwitchjavascript

一、index.htmlcss

<!DOCTYPE html>
<html lang="zh">

    <head>
        <meta charset="UTF-8" />
        <title>基於Vue開發的標籤頁組件</title>
        <link rel="stylesheet" type="text/css" href="css/style.css" />
    </head>

    <body>
        <div id="app" v-cloak>
            <!--設置value便於父組件與子組件通訊-->
            <tabs v-model='value'>
                <pane label="標籤一" name='1'> 標籤一的內容 </pane>
                <pane label="標籤二" name='2'> 標籤二的內容 </pane>
                <pane label="標籤三" name='3'> 標籤三的內容 </pane>
            </tabs>
        </div>

        <script src="https://cdn.bootcss.com/vue/2.5.9/vue.min.js"></script>
        <script src="js/pane.js" type="text/javascript" charset="utf-8"></script>
        <script src="js/tabs.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            var app = new Vue({ el: '#app', data: { //初始顯示第幾個
 value: '1' } }); </script>
    </body>

</html>

 

二、tabs.jshtml

Vue.component('tabs', { template: ` <div class="tabs">
            <div class="tabs-bar">
                <!--標題頁的標題 v-for遍歷, :class 動態綁定class-->
                <div :class="tabCls(item)" v-for="(item,index) in navList" @click="handleChange(index)"> {{item.label}} </div>
            </div>
            <div class="tabs-content">
                <!--這裏的slot就是嵌套的pane組件的內容-->
                <slot></slot>
            </div>
        </div>
 `, data: function() { return { //將pane的標題保存到數組中
 navList: [], //保存父組件的value到currentValue變量中,以便在本地維護
            currentValue: this.value } }, props: { //接收父組件的value
 value: { type: [String] } }, methods: { //使用$children遍歷子組件,獲得全部的pane組件
        getTabs: function() { return this.$children.filter(function(item) { return item.$options.name === 'pane'; }) }, //更新tabs
 updateNav() { this.navList = []; var _this = this; this.getTabs().forEach(function(pane, index) { _this.navList.push({ label: pane.label, name: pane.name || index }); //若是沒有設置name,默認設置爲索引值
                if(!pane.name) { pane.name = index; } //設置第一個pane爲當前顯示的tab
                if(index === 0) { if(!_this.currentValue) { _this.currentValue = pane.name || index; } } }); this.updateStatus(); }, updateStatus() { var tabs = this.getTabs(); var _this = this; //顯示當前選中的tab對應的pane組件,隱藏沒有選中的
            tabs.forEach(function(tab) { return tab.show = tab.name === _this.currentValue; }) }, tabCls: function(item) { return [ 'tabs-tab', { //爲當前選中的tab加一個tabs-tab-active class
                    'tabs-tab-active': item.name === this.currentValue } ] }, //點擊tab標題觸發
        handleChange: function(index) { var nav = this.navList[index]; var name = nav.name; //改變當前選中的tab,觸發watch
            this.currentValue = name; //實現子組件與父組件通訊
            this.$emit('input', name); } }, watch: { value: function(val) { this.currentValue = val; }, currentValue: function() { //tab發生變化時,更新pane的顯示狀態
            this.updateStatus(); } } })

 

三、pane.jsvue

Vue.component('pane',{ template:` <div class="pane" v-show="show">        
        <slot></slot>
    </div>
 `, data:function(){ return { show:true } }, //props爲來自父組件的變量,實現父組件與子組件通訊
 props:{ //設置pane的標識
 name:{ type:String }, //label是設置標題
 label:{ type:String, default:'' } }, methods:{ updateNav:function(){ //$parent 父鏈,通知父組件(tabs)進行更新。
            //說明:在業務中儘量不要使用$parent來操做父組件,$parent適合標籤頁這樣的獨立組件
            this.$parent.updateNav(); } }, //監聽label
 watch:{ label(){ this.updateNav(); } }, mounted(){ //初始化tabs
        this.updateNav(); } })

 

四、style.cssjava

[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: #fff; border: 1px solid #d7dde4; cursor: pointer; position: relative;
} .tabs-tab-active{ color: #3399ff; border-top: 1px solid #3399ff; border-bottom: 1px solid #3399ff;
} .tabs-tab-active:before{ content: ''; display: block; height: 1px; background: #3399ff; position: absolute; top: 0; left: 0; right: 0;
} .tabs-content{ padding: 8px 0;
}

五、效果:git

相關文章
相關標籤/搜索