257 lines
6.5 KiB
JavaScript
257 lines
6.5 KiB
JavaScript
import nodeUtil from '../core/utils/node-util';
|
||
|
||
Component({
|
||
externalClasses: [
|
||
'l-class-header',
|
||
'l-class-active',
|
||
'l-class-inactive',
|
||
'l-class-line',
|
||
'l-class-tabimage',
|
||
'l-header-class',
|
||
'l-active-class',
|
||
'l-inactive-class',
|
||
'l-line-class',
|
||
'l-tabimage-class',
|
||
'l-content-class'
|
||
],
|
||
relations: {
|
||
'../tabpanel/index': {
|
||
type: 'child'
|
||
},
|
||
linked() {
|
||
// 每次有子节点被插入时执行,target是该节点实例对象,触发在该节点attached生命周期之后
|
||
this.initTabs();
|
||
}
|
||
},
|
||
options: {
|
||
multipleSlots: true // 在组件定义时的选项中启用多slot支持
|
||
},
|
||
/**
|
||
* 组件的属性列表
|
||
*/
|
||
properties: {
|
||
activeKey: {
|
||
type: String,
|
||
value: '',
|
||
observer: 'changeCurrent'
|
||
},
|
||
placement: {
|
||
type: String,
|
||
value: 'top'
|
||
},
|
||
aminmated: Boolean,
|
||
scrollable: Boolean,
|
||
swipeable: {
|
||
type: Boolean,
|
||
value: true
|
||
},
|
||
hasLine: {
|
||
type: Boolean,
|
||
value: true
|
||
},
|
||
activeColor: {
|
||
type: String,
|
||
value: '#333333'
|
||
},
|
||
inactiveColor: {
|
||
type: String,
|
||
value: '#bbbbbb'
|
||
}
|
||
},
|
||
|
||
data: {
|
||
tabList: [],
|
||
currentIndex: 0,
|
||
transformX: 0,
|
||
transformY: 0
|
||
},
|
||
|
||
ready() {
|
||
this.initTabs();
|
||
},
|
||
|
||
/**
|
||
* 组件的方法列表
|
||
*/
|
||
methods: {
|
||
initTabs() {
|
||
this.initTabList();
|
||
this.initActiveIndex();
|
||
},
|
||
initActiveIndex(val = this.data.activeKey) {
|
||
let activeKey = val,
|
||
currentIndex = this.data.currentIndex;
|
||
this.data.tabList.forEach((item, index) => {
|
||
activeKey = !val && index === 0 ? item.key : activeKey;
|
||
currentIndex = item.key === activeKey ? index : currentIndex;
|
||
});
|
||
this.setData(
|
||
{
|
||
activeKey,
|
||
currentIndex
|
||
},
|
||
() => {
|
||
if (this.data.scrollable) {
|
||
this.queryMultipleNodes();
|
||
}
|
||
}
|
||
);
|
||
},
|
||
|
||
initTabList() {
|
||
let items = this.getRelationNodes('../tabpanel/index');
|
||
if (items.length > 0) {
|
||
const tabList = [];
|
||
items.forEach(item => {
|
||
const tabIndex = tabList.findIndex(
|
||
tabItem => tabItem.tab === item.data.tab
|
||
);
|
||
let tab = {};
|
||
if (tabIndex === -1) {
|
||
tab = {
|
||
tab: item.data.tab,
|
||
key: item.data.key,
|
||
icon: item.data.icon,
|
||
iconStyle: item.data.iconStyle,
|
||
image: item.data.image,
|
||
subTabs: []
|
||
};
|
||
tabList.push(tab);
|
||
}
|
||
const targetTab = tabIndex === -1 ? tab : tabList[tabIndex];
|
||
if (item.data.subTab) {
|
||
targetTab.subTabs = targetTab.subTabs || [];
|
||
const subTabItem = {
|
||
tab: item.data.subTab,
|
||
key: item.data.subKey
|
||
};
|
||
targetTab.subTabs.push(subTabItem);
|
||
targetTab.activeSubKey =
|
||
this.data.subActiveKey || targetTab.subTabs[0].key;
|
||
targetTab.subCurrentIndex = 0;
|
||
}
|
||
});
|
||
this.setData({
|
||
tabList
|
||
});
|
||
}
|
||
},
|
||
swiperChange(e) {
|
||
const {source, current} = e.detail;
|
||
if (source === 'touch') {
|
||
const currentIndex = current;
|
||
const activeKey = this.data.tabList[current].key;
|
||
const subCurrentIndex = this.data.tabList[currentIndex].subCurrentIndex;
|
||
const activeSubKey = this.data.tabList[currentIndex].activeSubKey;
|
||
this._setChangeData({
|
||
activeKey,
|
||
currentIndex,
|
||
subCurrentIndex,
|
||
activeSubKey
|
||
});
|
||
}
|
||
},
|
||
subSwiperChange(e) {
|
||
const {source, current} = e.detail;
|
||
if (source === 'touch') {
|
||
const {currentIndex, activeKey} = this.data;
|
||
const subCurrentIndex = current;
|
||
const activeSubKey = this.data.tabList[currentIndex].subTabs[
|
||
subCurrentIndex
|
||
].key;
|
||
const tabs = this.data.tabList[currentIndex];
|
||
tabs.activeSubKey = activeSubKey;
|
||
tabs.subCurrentIndex = subCurrentIndex;
|
||
|
||
this.setData({
|
||
[`tabList[${currentIndex}]`]: tabs
|
||
});
|
||
|
||
this._setChangeData({
|
||
activeKey,
|
||
currentIndex,
|
||
activeSubKey,
|
||
subCurrentIndex
|
||
});
|
||
}
|
||
},
|
||
handleChange(e) {
|
||
const isSubHeader = e.currentTarget.dataset.headerType === 'subTab';
|
||
const {currentIndex, activeKey} = this.data;
|
||
|
||
const clickIndex = e.currentTarget.dataset.index;
|
||
const subCurrentIndex = isSubHeader
|
||
? clickIndex
|
||
: this.data.tabList[clickIndex].subCurrentIndex;
|
||
const activeSubKey = isSubHeader
|
||
? this.data.tabList[currentIndex].subTabs[subCurrentIndex].key
|
||
: this.data.tabList[clickIndex].activeSubKey;
|
||
if (isSubHeader) {
|
||
const tabs = this.data.tabList[currentIndex];
|
||
tabs.activeSubKey = activeSubKey;
|
||
tabs.subCurrentIndex = subCurrentIndex;
|
||
this.setData({
|
||
[`tabList[${currentIndex}]`]: tabs
|
||
});
|
||
this._setChangeData({
|
||
activeKey,
|
||
currentIndex,
|
||
activeSubKey,
|
||
subCurrentIndex
|
||
});
|
||
} else {
|
||
const activeKey = e.currentTarget.dataset.key;
|
||
this._setChangeData({
|
||
activeKey,
|
||
currentIndex: clickIndex,
|
||
subCurrentIndex,
|
||
activeSubKey
|
||
});
|
||
}
|
||
},
|
||
|
||
_setChangeData({
|
||
activeKey,
|
||
currentIndex,
|
||
activeSubKey = '',
|
||
subCurrentIndex = null
|
||
}) {
|
||
this.setData(
|
||
{
|
||
activeKey,
|
||
currentIndex
|
||
},
|
||
() => {
|
||
if (this.data.scrollable) {
|
||
this.queryMultipleNodes();
|
||
}
|
||
}
|
||
);
|
||
this.triggerEvent('linchange', {
|
||
activeKey,
|
||
currentIndex,
|
||
activeSubKey,
|
||
subCurrentIndex
|
||
});
|
||
},
|
||
|
||
async queryMultipleNodes() {
|
||
const {placement, activeKey, tabList} = this.data;
|
||
const res = await nodeUtil.getNodeRectFromComponent(this, '#' + activeKey);
|
||
if (['top', 'bottom'].indexOf(placement) !== -1) {
|
||
this.setData({
|
||
transformX: res.left - (tabList.length / 2) * res.width,
|
||
transformY: 0
|
||
});
|
||
} else {
|
||
const navRect = await nodeUtil.getNodeRectFromComponent(this, '.l-tabs-header');
|
||
const transformY = res.top - navRect.top - navRect.height / 2;
|
||
this.setData({
|
||
transformX: 0,
|
||
transformY: transformY
|
||
});
|
||
}
|
||
}
|
||
}
|
||
});
|