低下頭看了看自己的手環。距離自己的flag已經跳票3天了。。。
不為什麼,因為我懶#滑稽 #滑稽#滑稽
咳咳,我們們今天進入正題---Tab元件的編寫
首先還是先看Tab預覽圖:
Tab預覽圖
很簡單的功能,很簡潔的UI。
首先還是獻上Tab html程式碼和css程式碼(我css基礎不好 各位可以忽略#滑稽)
為了自由度高一點,我們採用 Tab+TabPanel 的方式製作。這種製作方式也是大部分UI框架的製作方式
Tab-HTML程式碼
<template>
<div class="tab-wrapper">
<div class="tab__header">
<div class="tab__header__item">
<div style="width: 100%;">
<div class="tab__item">
<span>驗證碼登入</span>
</div>
<div class="tab__item">
<span>密碼登入</span>
</div>
</div>
</div>
</div>
<div class="tab__content">
<slot></slot>
</div>
</div>
</template>複製程式碼
Tab-CSS程式碼
<style scoped>
.iconfont {
font-size: 1.5rem;
}
.tab__header {
display: flex;
}
.tab__header__item {
margin: 0;
}
.tab__header__item > div {
display: flex;
flex-direction: row;
white-space: nowrap;
transition: transform .3s;
}
.tab__item {
font-size: 1.3rem;
cursor: pointer;
margin-right: 1rem;
flex: 1;
text-align: center;
}
.tab--active > span {
border-bottom: 2px solid #1890FF;
color: #1890FF;
padding-bottom: .5rem;
}
.tab__header__btn--left {
margin-right: .5rem;
cursor: pointer;
}
.tab__header__btn--right {
margin-left: .5rem;
cursor: pointer;
}
.tab--panel-wrapper {
display: none;
}
.tab--panel-wrapper--active {
display: block !important;
}
</style>
複製程式碼
TabPanel程式碼:
<template>
<div class="tab--panel-wrapper" :name="name">
<div class="tab--panel-content">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
name: "ZbTabPanel",
props: {
name: { //Tab模組名
required: true
}
}
}
</script>
<style scoped>
</style>
複製程式碼
先開始製作基礎功能:Tab切換
Tab切換功能的製作
首先一上來就會出現理解性的問題:
以往我們寫Tab 頭部寫頭部的東西,內容寫內容的東西。兩者分開來寫。便於理解
但如果是這種元件套元件的方式,看起來用法簡單了不少。但是增加了編寫難度
還有一點,父元件怎麼去控制子元件的顯示隱藏情況?
那就一步步來唄。
為了方便便於編寫起來好理解。我選擇內容插入,頭部遍歷的方式去製作
<template>
<div class="tab-wrapper">
<div class="tab__header" ref="tabHeaderItem">
<div class="tab__header__item">
<div style="width: 100%;">
<div class="tab__item"
@click="tabItemClick(item.name,key)" //tab的點選事件
@touchstart="tabItemClick(item.name,key)" //tab的移動端點選事件
v-for="(item,key) in tabList" //迴圈list
:class="{'tab--active':activeTab.index===key}"> //如果當前tabtitle的下標 =已啟用的tabtitle下標
<span>{{item.name}}</span>
</div>
</div>
</div>
</div>
<div class="tab__content"
ref="content">
<slot></slot>
</div>
</div>
</template>
複製程式碼
js方面:
data() {
return {
tabList: [], //tab標題列表
activeTab: { //已啟用的tab資訊
index: 0, //下標
name: '' //名稱
}
}
}複製程式碼
既然是插槽slot,那我們就用點插槽該做的事情 #嘿嘿嘿
於是我在 mounted 函式內,看一下$slot的內容
結果還真的有
不過出現了一個空插槽值。。。但是無關緊要,我們可以加一層空值判斷嘛~~
let self = this; //外層新建變數引用this
this.$slots.default.forEach((components) => { //迴圈default內的內容
if (components.tag && components.componentOptions) { //如果子元素tag鍵&&componentOptions有內容。
self.tabList.push(components.componentOptions.propsData)
// 在components.componentOptions這個鍵內 有propsDate這個屬性。我們可以通過這個屬性拿到子元件的props值
}
});
this.$nextTick(() => { //避免data未更新
this.activeTab = { //給activeTab賦初始值
index: 0, //預設選中第一個
name: this.tabList[0].name //尋找tabList第一個元素 還有他的名字
};
});複製程式碼
這樣切換頭部功能實現了。但是底部主體內容無動於衷
所以我們在watch函式內,監聽一下activeTab變數的資料變化:
watch: {
activeTab(newValue, oldValue) {
this.$refs.content.children[oldValue.index].className = "tab--panel-wrapper";
this.$refs.content.children[newValue.index].className = "tab--panel-wrapper--active";
}
}複製程式碼
這樣基礎內容就大功告成了。
用法參考
<zb-tab>
<zb-tab-panel name="驗證碼登入">
<!--這是驗證碼登入的內容-->
</zb-tab-panel>
<zb-tab-panel name="密碼登入">
<!--這是密碼登入的內容-->
</zb-tab-panel>
</zb-tab>複製程式碼
因為name屬性不能少 所以是必填
這樣一來遇到個問題,我們的tab是用flex編寫的。但是如果tab多了橫向滾動怎麼辦?
這裡安利一個滴滴出行@ustbhuangyi 開發的滾動元件: better-scroll
首先我們先安裝他:
npm install better-scroll --save複製程式碼
接著在vue元件內引入:
import BScroll from 'better-scroll'複製程式碼
這裡不做過多介紹。所以我們簡單使用。詳細使用請看文件
_initScroll: function () {
new BScroll(this.$refs.tabHeaderItem, {
scrollX: true, //是否支援X滾動
bounce: true //是否開啟回彈動畫
});
}複製程式碼
掛載函式內
setTimeout(() => {
this.$nextTick(() => { //避免data未更新
this._initScroll();
}
)
}, 20)複製程式碼
如果看到行內樣式有css動畫。說明就掛載成功了
這樣遇到了一個小bug。掛載成功是可以。但是無法滾動。如圖
經查:是因為他掛載的那個元素,我們寫個width:100%。導致他丟失了實際長度。無法掛載。
但是去掉width:100%後,元素始終不會平鋪開。會左浮動一樣的排列
所以我們為了兩種都要,加個props外部控制吧~~
props: {
floatLeft: { //是否開啟左浮動模式
default: false
}
}複製程式碼
html:
<div class="tab__header__item"
:style="floatLeft? '': 'width:100%'">複製程式碼
這樣一個不算很完美的tab就完成了。希望製作思想可以幫到大家