概述
選項卡切換組件,常用於平級區域大塊內容的的收納和展現。
源碼地址:https://github.com/iview/iview/tree/2.0/src/components/tabs
使用:
<template>
<Tabs name="first">
<TabPane label="macOS" icon="logo-apple" tab="first">
<Tabs name="second" >
<TabPane label="macOS" icon="logo-apple" tab="second">標籤一的內容</TabPane>
<TabPane label="Windows" icon="logo-windows" tab="second">標籤二的內容</TabPane>
<TabPane label="Linux" icon="logo-tux" tab="second">標籤三的內容</TabPane>
</Tabs>
</TabPane>
<TabPane label="Windows" icon="logo-windows" tab="first">標籤二的內容</TabPane>
</Tabs>
</template>
在源碼的tabs文件下有三個文件:index.js,tabs.vue,pane.vue
index.js中引入了tabs.vue和pane.vue.
import Tabs from './tabs.vue';
import Pane from './pane.vue';
Tabs.Pane = Pane;
export default Tabs;
tabs.vue
tabs.vue是整個組件的容器,分爲三部分:
1 通過<slot name="extra"></slot> 擴展tabs選項的附加內容。
2 通過this.$children獲取tabs下的每一個TabPane並放進navLIst,遍歷navLIst設置tabs選項標籤。
3 聲明slot接收整個panes。
this.$children查找當前組件的直接子組件,可以遍歷全部子組件, 需要注意 $children 並不保證順序,也不是響應式的。
slot 插槽
父級模板裏的所有內容都是在父級作用域中編譯的;子模板裏的所有內容都是在子作用域中編譯的。Slot分發的內容,作用域是在父組件上
<template>
<div :class="classes">
<div :class="[prefixCls + '-bar']">
<div :class="[prefixCls + '-nav-right']" v-if="showSlot"><slot name="extra"></slot></div>
<div
:class="[prefixCls + '-nav-container']"
tabindex="0"
ref="navContainer"
@keydown="handleTabKeyNavigation"
@keydown.space.prevent="handleTabKeyboardSelect(false)"
>
<div ref="navWrap" :class="[prefixCls + '-nav-wrap', scrollable ? prefixCls + '-nav-scrollable' : '']">
<span :class="[prefixCls + '-nav-prev', scrollable ? '' : prefixCls + '-nav-scroll-disabled']" @click="scrollPrev"><Icon type="ios-arrow-back"></Icon></span>
<span :class="[prefixCls + '-nav-next', scrollable ? '' : prefixCls + '-nav-scroll-disabled']" @click="scrollNext"><Icon type="ios-arrow-forward"></Icon></span>
<div ref="navScroll" :class="[prefixCls + '-nav-scroll']">
<div ref="nav" :class="[prefixCls + '-nav']" :style="navStyle">
<div :class="barClasses" :style="barStyle"></div>
<div :class="tabCls(item)" v-for="(item, index) in navList" @click="handleChange(index)">
<Icon v-if="item.icon !== ''" :type="item.icon"></Icon>
<Render v-if="item.labelType === 'function'" :render="item.label"></Render>
<template v-else>{{ item.label }}</template>
<Icon :class="[prefixCls + '-close']" v-if="showClose(item)" :type="arrowType" :custom="customArrowType" :size="arrowSize" @click.native.stop="handleRemove(index)"></Icon>
</div>
</div>
</div>
</div>
</div>
</div>
<div :class="contentClasses" :style="contentStyle" ref="panes"><slot></slot></div>
</div>
</template>
pane.vue
pane窗格文件主要作用是,接收傳進來name,label,icon,disabled,closable,tab,index參數,和父組件傳進來的注入inject: ['TabsInstance'],以獲取父組件的this引用.以便在參數及銷燬時調用父組件的updateNav更新每一個tab.
provide/inject
在vue中不同組件通信方式如下:
1.父子組件,通過prop
2.非父子組件,通過vuex或根vue轉載器
通常是以上兩種情況,然而還有一種比較特殊的情況,即孫子組件或更深層次的組件通信
爲什麼不用vuex,簡單省事????
有很多爲了這個引入vuex會導致代碼性價比比較低,項目本身沒有使用vuex的必要
1.provide就相當於加強版父組件prop
2.inject就相當於加強版子組件的props
缺點
這麼做也是有明顯的缺點的,在任意層級都能訪問導致數據追蹤比較困難,因此這個屬性通常並不建議使用。能用vuex的使用vuex,但是在做組件庫開發時,不對vuex進行依賴,且不知道用戶使用環境的情況下可以很好的使用
<template>
<div :class="prefixCls" v-show="show" :style="contentStyle"><slot></slot></div>
</template>
<script>
const prefixCls = 'ivu-tabs-tabpane';
export default {
name: 'TabPane',
inject: ['TabsInstance'],
props: {
name: {
type: String
},
label: {
type: [String, Function],
default: ''
},
icon: {
type: String
},
disabled: {
type: Boolean,
default: false
},
closable: {
type: Boolean,
default: null
},
// Tabs 嵌套時,用 tab 區分層級,指向對應的 Tabs 的 name
tab: {
type: String
},
// 在 TabPane 使用 v-if 時,並不會按照預先的順序渲染,這時可設置 index,並從小到大排序
// 數值需大於 0
index: {
type: Number
}
},
data () {
return {
prefixCls: prefixCls,
show: true,
currentName: this.name
};
},
computed: {
contentStyle () {
return {
visibility: this.TabsInstance.activeKey !== this.currentName ? 'hidden' : 'visible'
};
}
},
methods: {
updateNav () {
this.TabsInstance.updateNav();
}
},
watch: {
name (val) {
this.currentName = val;
this.updateNav();
},
label () {
this.updateNav();
},
icon () {
this.updateNav();
},
disabled () {
this.updateNav();
}
},
mounted () {
this.updateNav();
},
destroyed () {
this.updateNav();
}
};
</script>