[improvement] Tabs: use relation mixin

This commit is contained in:
陈嘉涵 2019-05-07 10:06:57 +08:00
parent 912d691f9e
commit c1da495cb7
4 changed files with 43 additions and 48 deletions

View File

@ -1,11 +1,11 @@
/* eslint-disable object-shorthand */ /* eslint-disable object-shorthand */
import { use } from '../utils'; import { use } from '../utils';
import { FindParentMixin } from '../mixins/find-parent'; import { ChildrenMixin } from '../mixins/relation';
const [sfc, bem] = use('tab'); const [sfc, bem] = use('tab');
export default sfc({ export default sfc({
mixins: [FindParentMixin], mixins: [ChildrenMixin('vanTabs')],
props: { props: {
title: String, title: String,
@ -19,10 +19,6 @@ export default sfc({
}, },
computed: { computed: {
index() {
return this.parent.tabs.indexOf(this);
},
selected() { selected() {
return this.index === this.parent.curActive; return this.index === this.parent.curActive;
} }
@ -38,24 +34,12 @@ export default sfc({
} }
}, },
created() {
this.findParent('van-tabs');
},
mounted() { mounted() {
const { tabs } = this.parent;
const index = this.parent.slots().indexOf(this.$vnode);
tabs.splice(index === -1 ? tabs.length : index, 0, this);
if (this.slots('title')) { if (this.slots('title')) {
this.parent.renderTitle(this.$refs.title, this.index); this.parent.renderTitle(this.$refs.title, this.index);
} }
}, },
beforeDestroy() {
this.parent.tabs.splice(this.index, 1);
},
render(h) { render(h) {
const { slots } = this; const { slots } = this;
const shouldRender = this.inited || !this.parent.lazyRender; const shouldRender = this.inited || !this.parent.lazyRender;

View File

@ -6,15 +6,16 @@ exports[`change tabs data 1`] = `
<div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;"> <div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
<div class="van-tabs__line" style="background-color: rgb(255, 68, 68);"></div> <div class="van-tabs__line" style="background-color: rgb(255, 68, 68);"></div>
<div class="van-tab van-tab--active"><span class="van-ellipsis">title1</span></div> <div class="van-tab van-tab--active"><span class="van-ellipsis">title1</span></div>
<div class="van-tab"><span class="van-ellipsis"></span></div> <div class="van-tab">
<div><span>title2</span></div>
</div>
<div class="van-tab van-tab--disabled"><span class="van-ellipsis">title3</span></div> <div class="van-tab van-tab--disabled"><span class="van-ellipsis">title3</span></div>
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tab__pane" style="">Text</div> <div class="van-tab__pane">Text</div>
<div class="van-tab__pane" style="display: none;"> <div class="van-tab__pane" style="display: none;">
<!----> <!---->
<div><span>title2</span></div>
</div> </div>
<div class="van-tab__pane" style="display: none;"> <div class="van-tab__pane" style="display: none;">
<!----> <!---->
@ -35,7 +36,7 @@ exports[`change tabs data 2`] = `
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tab__pane" style="">Text</div> <div class="van-tab__pane">Text</div>
<div class="van-tab__pane" style="display: none;"> <div class="van-tab__pane" style="display: none;">
<!----> <!---->
</div> </div>
@ -105,7 +106,7 @@ exports[`lazy render 1`] = `
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tab__pane" style="">Text</div> <div class="van-tab__pane">Text</div>
<div class="van-tab__pane" style="display: none;"> <div class="van-tab__pane" style="display: none;">
<!----> <!---->
<div><span>title2</span></div> <div><span>title2</span></div>
@ -130,7 +131,7 @@ exports[`lazy render 2`] = `
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tab__pane" style="">Text</div> <div class="van-tab__pane">Text</div>
<div class="van-tab__pane" style="display: none;"> <div class="van-tab__pane" style="display: none;">
Text Text
</div> </div>
@ -149,7 +150,7 @@ exports[`render nav-left & nav-right slot 1`] = `
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tab__pane" style="">Text</div> <div class="van-tab__pane">Text</div>
<div class="van-tab__pane" style="display: none;"> <div class="van-tab__pane" style="display: none;">
<!----> <!---->
<div><span>title2</span></div> <div><span>title2</span></div>
@ -165,7 +166,7 @@ exports[`swipe to switch tab 1`] = `
<div class="van-tabs van-tabs--line"> <div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom"> <div class="van-tabs__wrap van-hairline--top-bottom">
<div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;"> <div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
<div class="van-tabs__line" style="background-color: rgb(255, 68, 68); width: 2px; transform: translateX(-1px);"></div> <div class="van-tabs__line" style="background-color: rgb(255, 68, 68);"></div>
<div class="van-tab van-tab--active"><span class="van-ellipsis">title1</span></div> <div class="van-tab van-tab--active"><span class="van-ellipsis">title1</span></div>
<div class="van-tab"> <div class="van-tab">
<div><span>title2</span></div> <div><span>title2</span></div>
@ -174,7 +175,7 @@ exports[`swipe to switch tab 1`] = `
</div> </div>
</div> </div>
<div class="van-tabs__content"> <div class="van-tabs__content">
<div class="van-tab__pane" style="">Text</div> <div class="van-tab__pane">Text</div>
<div class="van-tab__pane" style="display: none;"> <div class="van-tab__pane" style="display: none;">
<!----> <!---->
</div> </div>
@ -189,9 +190,9 @@ exports[`swipe to switch tab 2`] = `
<div class="van-tabs van-tabs--line"> <div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom"> <div class="van-tabs__wrap van-hairline--top-bottom">
<div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;"> <div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
<div class="van-tabs__line" style="background-color: rgb(255, 68, 68); width: 2px; transform: translateX(-1px);"></div> <div class="van-tabs__line" style="background-color: rgb(255, 68, 68);"></div>
<div class="van-tab"><span class="van-ellipsis">title1</span></div> <div class="van-tab van-tab--active"><span class="van-ellipsis">title1</span></div>
<div class="van-tab van-tab--active"> <div class="van-tab">
<div><span>title2</span></div> <div><span>title2</span></div>
</div> </div>
<div class="van-tab van-tab--disabled"><span class="van-ellipsis">title3</span></div> <div class="van-tab van-tab--disabled"><span class="van-ellipsis">title3</span></div>
@ -213,9 +214,9 @@ exports[`swipe to switch tab 3`] = `
<div class="van-tabs van-tabs--line"> <div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom"> <div class="van-tabs__wrap van-hairline--top-bottom">
<div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;"> <div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
<div class="van-tabs__line" style="background-color: rgb(255, 68, 68); width: 2px; transform: translateX(-1px);"></div> <div class="van-tabs__line" style="background-color: rgb(255, 68, 68);"></div>
<div class="van-tab"><span class="van-ellipsis">title1</span></div> <div class="van-tab van-tab--active"><span class="van-ellipsis">title1</span></div>
<div class="van-tab van-tab--active"> <div class="van-tab">
<div><span>title2</span></div> <div><span>title2</span></div>
</div> </div>
<div class="van-tab van-tab--disabled"><span class="van-ellipsis">title3</span></div> <div class="van-tab van-tab--disabled"><span class="van-ellipsis">title3</span></div>
@ -237,7 +238,7 @@ exports[`swipe to switch tab 4`] = `
<div class="van-tabs van-tabs--line"> <div class="van-tabs van-tabs--line">
<div class="van-tabs__wrap van-hairline--top-bottom"> <div class="van-tabs__wrap van-hairline--top-bottom">
<div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;"> <div class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
<div class="van-tabs__line" style="background-color: rgb(255, 68, 68); width: 2px; transform: translateX(-1px);"></div> <div class="van-tabs__line" style="background-color: rgb(255, 68, 68);"></div>
<div class="van-tab van-tab--active"><span class="van-ellipsis">title1</span></div> <div class="van-tab van-tab--active"><span class="van-ellipsis">title1</span></div>
<div class="van-tab"> <div class="van-tab">
<div><span>title2</span></div> <div><span>title2</span></div>

View File

@ -88,6 +88,8 @@ test('swipe to switch tab', async () => {
test('change tabs data', async () => { test('change tabs data', async () => {
const wrapper = createWrapper(); const wrapper = createWrapper();
await later();
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
wrapper.setData({ wrapper.setData({

View File

@ -2,13 +2,19 @@ import { use, isDef } from '../utils';
import { raf } from '../utils/raf'; import { raf } from '../utils/raf';
import { on, off } from '../utils/event'; import { on, off } from '../utils/event';
import { TouchMixin } from '../mixins/touch'; import { TouchMixin } from '../mixins/touch';
import { setScrollTop, getScrollTop, getElementTop, getScrollEventTarget } from '../utils/scroll'; import { ParentMixin } from '../mixins/relation';
import {
setScrollTop,
getScrollTop,
getElementTop,
getScrollEventTarget
} from '../utils/scroll';
const [sfc, bem] = use('tabs'); const [sfc, bem] = use('tabs');
const tabBem = use('tab')[1]; const tabBem = use('tab')[1];
export default sfc({ export default sfc({
mixins: [TouchMixin], mixins: [TouchMixin, ParentMixin('vanTabs')],
model: { model: {
prop: 'active' prop: 'active'
@ -59,7 +65,6 @@ export default sfc({
data() { data() {
return { return {
tabs: [],
position: '', position: '',
curActive: null, curActive: null,
lineStyle: { lineStyle: {
@ -76,7 +81,7 @@ export default sfc({
computed: { computed: {
// whether the nav is scrollable // whether the nav is scrollable
scrollable() { scrollable() {
return this.tabs.length > this.swipeThreshold || !this.ellipsis; return this.children.length > this.swipeThreshold || !this.ellipsis;
}, },
wrapStyle() { wrapStyle() {
@ -124,7 +129,7 @@ export default sfc({
this.setLine(); this.setLine();
}, },
tabs() { children() {
this.correctActive(this.curActive || this.active); this.correctActive(this.curActive || this.active);
this.scrollIntoView(); this.scrollIntoView();
this.setLine(); this.setLine();
@ -218,7 +223,7 @@ export default sfc({
/* istanbul ignore else */ /* istanbul ignore else */
if (deltaX > 0 && curActive !== 0) { if (deltaX > 0 && curActive !== 0) {
this.setCurActive(curActive - 1); this.setCurActive(curActive - 1);
} else if (deltaX < 0 && curActive !== this.tabs.length - 1) { } else if (deltaX < 0 && curActive !== this.children.length - 1) {
this.setCurActive(curActive + 1); this.setCurActive(curActive + 1);
} }
} }
@ -283,8 +288,8 @@ export default sfc({
// correct the value of active // correct the value of active
correctActive(active) { correctActive(active) {
active = +active; active = +active;
const exist = this.tabs.some(tab => tab.index === active); const exist = this.children.some(tab => tab.index === active);
const defaultActive = (this.tabs[0] || {}).index || 0; const defaultActive = (this.children[0] || {}).index || 0;
this.setCurActive(exist ? active : defaultActive); this.setCurActive(exist ? active : defaultActive);
}, },
@ -294,7 +299,7 @@ export default sfc({
this.$emit('input', active); this.$emit('input', active);
if (this.curActive !== null) { if (this.curActive !== null) {
this.$emit('change', active, this.tabs[active].title); this.$emit('change', active, this.children[active].title);
} }
this.curActive = active; this.curActive = active;
} }
@ -304,8 +309,8 @@ export default sfc({
const diff = reverse ? -1 : 1; const diff = reverse ? -1 : 1;
let index = active; let index = active;
while (index >= 0 && index < this.tabs.length) { while (index >= 0 && index < this.children.length) {
if (!this.tabs[index].disabled) { if (!this.children[index].disabled) {
return index; return index;
} }
index += diff; index += diff;
@ -314,7 +319,7 @@ export default sfc({
// emit event when clicked // emit event when clicked
onClick(index) { onClick(index) {
const { title, disabled } = this.tabs[index]; const { title, disabled } = this.children[index];
if (disabled) { if (disabled) {
this.$emit('disabled', index, title); this.$emit('disabled', index, title);
} else { } else {
@ -400,7 +405,7 @@ export default sfc({
render(h) { render(h) {
const { type, ellipsis, animated, scrollable } = this; const { type, ellipsis, animated, scrollable } = this;
const Nav = this.tabs.map((tab, index) => ( const Nav = this.children.map((tab, index) => (
<div <div
ref="tabs" ref="tabs"
refInFor refInFor
@ -425,7 +430,10 @@ export default sfc({
<div <div
ref="wrap" ref="wrap"
style={this.wrapStyle} style={this.wrapStyle}
class={[bem('wrap', { scrollable }), { 'van-hairline--top-bottom': type === 'line' }]} class={[
bem('wrap', { scrollable }),
{ 'van-hairline--top-bottom': type === 'line' }
]}
> >
<div ref="nav" class={bem('nav', [type])} style={this.navStyle}> <div ref="nav" class={bem('nav', [type])} style={this.navStyle}>
{this.slots('nav-left')} {this.slots('nav-left')}