mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
[improvement] Tab: extract content component (#3636)
This commit is contained in:
parent
e4d967a3f0
commit
d73e3be8c4
@ -57,11 +57,11 @@ exports[`change tabs data 2`] = `
|
|||||||
exports[`click to switch tab 1`] = `
|
exports[`click 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 role="tablist" class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
|
<div role="tablist" class="van-tabs__nav van-tabs__nav--line">
|
||||||
<div role="tab" aria-selected="true" class="van-tab van-tab--active"><span class="van-ellipsis">title1</span></div>
|
<div role="tab" aria-selected="true" class="van-tab van-tab--active"><span class="van-ellipsis">title1</span></div>
|
||||||
<div role="tab" class="van-tab"><span class="van-ellipsis">title2</span></div>
|
<div role="tab" class="van-tab"><span class="van-ellipsis">title2</span></div>
|
||||||
<div role="tab" class="van-tab van-tab--disabled"><span class="van-ellipsis">title3</span></div>
|
<div role="tab" class="van-tab van-tab--disabled"><span class="van-ellipsis">title3</span></div>
|
||||||
<div class="van-tabs__line" style="background-color: rgb(255, 68, 68); width: 2px; transform: translateX(0px) translateX(-50%);"></div>
|
<div class="van-tabs__line" style="width: 0px; transform: translateX(0px) translateX(-50%);"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="van-tabs__content">
|
<div class="van-tabs__content">
|
||||||
@ -79,11 +79,11 @@ exports[`click to switch tab 1`] = `
|
|||||||
exports[`click to switch tab 2`] = `
|
exports[`click 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 role="tablist" class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
|
<div role="tablist" class="van-tabs__nav van-tabs__nav--line">
|
||||||
<div role="tab" class="van-tab"><span class="van-ellipsis">title1</span></div>
|
<div role="tab" class="van-tab"><span class="van-ellipsis">title1</span></div>
|
||||||
<div role="tab" class="van-tab van-tab--active" aria-selected="true"><span class="van-ellipsis">title2</span></div>
|
<div role="tab" class="van-tab van-tab--active" aria-selected="true"><span class="van-ellipsis">title2</span></div>
|
||||||
<div role="tab" class="van-tab van-tab--disabled"><span class="van-ellipsis">title3</span></div>
|
<div role="tab" class="van-tab van-tab--disabled"><span class="van-ellipsis">title3</span></div>
|
||||||
<div class="van-tabs__line" style="background-color: rgb(255, 68, 68); width: 2px; transform: translateX(0px) translateX(-50%); transition-duration: 0.3s;"></div>
|
<div class="van-tabs__line" style="width: 0px; transform: translateX(0px) translateX(-50%); transition-duration: 0.3s;"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="van-tabs__content">
|
<div class="van-tabs__content">
|
||||||
@ -160,11 +160,11 @@ exports[`render nav-left & nav-right slot 1`] = `
|
|||||||
exports[`swipe to switch tab 1`] = `
|
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 role="tablist" class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
|
<div role="tablist" class="van-tabs__nav van-tabs__nav--line">
|
||||||
<div role="tab" aria-selected="true" class="van-tab van-tab--active"><span class="van-ellipsis">title1</span></div>
|
<div role="tab" aria-selected="true" class="van-tab van-tab--active"><span class="van-ellipsis">title1</span></div>
|
||||||
<div role="tab" class="van-tab"><span class="van-ellipsis">title2</span></div>
|
<div role="tab" class="van-tab"><span class="van-ellipsis">title2</span></div>
|
||||||
<div role="tab" class="van-tab van-tab--disabled"><span class="van-ellipsis">title3</span></div>
|
<div role="tab" class="van-tab van-tab--disabled"><span class="van-ellipsis">title3</span></div>
|
||||||
<div class="van-tabs__line" style="background-color: rgb(255, 68, 68);"></div>
|
<div class="van-tabs__line"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="van-tabs__content">
|
<div class="van-tabs__content">
|
||||||
@ -182,11 +182,11 @@ exports[`swipe to switch tab 1`] = `
|
|||||||
exports[`swipe to switch tab 2`] = `
|
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 role="tablist" class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
|
<div role="tablist" class="van-tabs__nav van-tabs__nav--line">
|
||||||
<div role="tab" aria-selected="true" class="van-tab van-tab--active"><span class="van-ellipsis">title1</span></div>
|
<div role="tab" aria-selected="true" class="van-tab van-tab--active"><span class="van-ellipsis">title1</span></div>
|
||||||
<div role="tab" class="van-tab"><span class="van-ellipsis">title2</span></div>
|
<div role="tab" class="van-tab"><span class="van-ellipsis">title2</span></div>
|
||||||
<div role="tab" class="van-tab van-tab--disabled"><span class="van-ellipsis">title3</span></div>
|
<div role="tab" class="van-tab van-tab--disabled"><span class="van-ellipsis">title3</span></div>
|
||||||
<div class="van-tabs__line" style="background-color: rgb(255, 68, 68);"></div>
|
<div class="van-tabs__line"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="van-tabs__content">
|
<div class="van-tabs__content">
|
||||||
@ -202,11 +202,11 @@ exports[`swipe to switch tab 2`] = `
|
|||||||
exports[`swipe to switch tab 3`] = `
|
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 role="tablist" class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
|
<div role="tablist" class="van-tabs__nav van-tabs__nav--line">
|
||||||
<div role="tab" aria-selected="true" class="van-tab van-tab--active"><span class="van-ellipsis">title1</span></div>
|
<div role="tab" aria-selected="true" class="van-tab van-tab--active"><span class="van-ellipsis">title1</span></div>
|
||||||
<div role="tab" class="van-tab"><span class="van-ellipsis">title2</span></div>
|
<div role="tab" class="van-tab"><span class="van-ellipsis">title2</span></div>
|
||||||
<div role="tab" class="van-tab van-tab--disabled"><span class="van-ellipsis">title3</span></div>
|
<div role="tab" class="van-tab van-tab--disabled"><span class="van-ellipsis">title3</span></div>
|
||||||
<div class="van-tabs__line" style="background-color: rgb(255, 68, 68);"></div>
|
<div class="van-tabs__line"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="van-tabs__content">
|
<div class="van-tabs__content">
|
||||||
@ -218,23 +218,3 @@ exports[`swipe to switch tab 3`] = `
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`swipe to switch tab 4`] = `
|
|
||||||
<div class="van-tabs van-tabs--line">
|
|
||||||
<div class="van-tabs__wrap van-hairline--top-bottom">
|
|
||||||
<div role="tablist" class="van-tabs__nav van-tabs__nav--line" style="border-color: #f44;">
|
|
||||||
<div role="tab" aria-selected="true" class="van-tab van-tab--active"><span class="van-ellipsis">title1</span></div>
|
|
||||||
<div role="tab" class="van-tab"><span class="van-ellipsis">title2</span></div>
|
|
||||||
<div role="tab" class="van-tab van-tab--disabled"><span class="van-ellipsis">title3</span></div>
|
|
||||||
<div class="van-tabs__line" style="background-color: rgb(255, 68, 68);"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="van-tabs__content">
|
|
||||||
<div role="tabpanel" class="van-tab__pane" style="">Text</div>
|
|
||||||
<div role="tabpanel" class="van-tab__pane" style="display: none;">Text</div>
|
|
||||||
<div role="tabpanel" class="van-tab__pane" style="display: none;">
|
|
||||||
<!---->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
@ -13,7 +13,6 @@ function createWrapper(options = {}) {
|
|||||||
:color="color"
|
:color="color"
|
||||||
:type="type"
|
:type="type"
|
||||||
:sticky="sticky"
|
:sticky="sticky"
|
||||||
:swipeable="swipeable"
|
|
||||||
:line-width="lineWidth"
|
:line-width="lineWidth"
|
||||||
:lazy-render="lazyRender"
|
:lazy-render="lazyRender"
|
||||||
@change="onChange"
|
@change="onChange"
|
||||||
@ -28,7 +27,6 @@ function createWrapper(options = {}) {
|
|||||||
return {
|
return {
|
||||||
color: '#f44',
|
color: '#f44',
|
||||||
type: 'line',
|
type: 'line',
|
||||||
swipeable: true,
|
|
||||||
sticky: true,
|
sticky: true,
|
||||||
lineWidth: 2,
|
lineWidth: 2,
|
||||||
lazyRender: true
|
lazyRender: true
|
||||||
@ -40,7 +38,14 @@ function createWrapper(options = {}) {
|
|||||||
|
|
||||||
test('click to switch tab', async () => {
|
test('click to switch tab', async () => {
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
const wrapper = createWrapper({
|
const wrapper = mount({
|
||||||
|
template: `
|
||||||
|
<van-tabs @change="onChange">
|
||||||
|
<van-tab title="title1">Text</van-tab>
|
||||||
|
<van-tab title="title2">Text</van-tab>
|
||||||
|
<van-tab title="title3" disabled>Text</van-tab>
|
||||||
|
</van-tabs>
|
||||||
|
`,
|
||||||
methods: {
|
methods: {
|
||||||
onChange
|
onChange
|
||||||
}
|
}
|
||||||
@ -59,7 +64,14 @@ test('click to switch tab', async () => {
|
|||||||
|
|
||||||
test('swipe to switch tab', async () => {
|
test('swipe to switch tab', async () => {
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
const wrapper = createWrapper({
|
const wrapper = mount({
|
||||||
|
template: `
|
||||||
|
<van-tabs swipeable @change="onChange">
|
||||||
|
<van-tab title="title1">Text</van-tab>
|
||||||
|
<van-tab title="title2">Text</van-tab>
|
||||||
|
<van-tab title="title3" disabled>Text</van-tab>
|
||||||
|
</van-tabs>
|
||||||
|
`,
|
||||||
methods: {
|
methods: {
|
||||||
onChange
|
onChange
|
||||||
}
|
}
|
||||||
@ -68,13 +80,14 @@ test('swipe to switch tab', async () => {
|
|||||||
const content = wrapper.find('.van-tabs__content');
|
const content = wrapper.find('.van-tabs__content');
|
||||||
await later();
|
await later();
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
|
||||||
triggerDrag(content, -100, 0);
|
triggerDrag(content, -100, 0);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
expect(onChange).toHaveBeenCalledTimes(1);
|
expect(onChange).toHaveBeenCalledTimes(1);
|
||||||
|
expect(onChange).toHaveBeenCalledWith(1, 'title2');
|
||||||
|
|
||||||
triggerDrag(content, -100, 0);
|
triggerDrag(content, -100, 0);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(onChange).toHaveBeenCalledTimes(1);
|
||||||
triggerDrag(content, 100, 0);
|
|
||||||
triggerDrag(content, 100, 0);
|
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
|
||||||
await later();
|
await later();
|
||||||
|
80
packages/tabs/Content.js
Normal file
80
packages/tabs/Content.js
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import { use } from '../utils';
|
||||||
|
import { TouchMixin } from '../mixins/touch';
|
||||||
|
|
||||||
|
const [sfc, bem] = use('tabs');
|
||||||
|
const MIN_SWIPE_DISTANCE = 50;
|
||||||
|
|
||||||
|
export default sfc({
|
||||||
|
mixins: [TouchMixin],
|
||||||
|
|
||||||
|
props: {
|
||||||
|
count: Number,
|
||||||
|
active: Number,
|
||||||
|
duration: Number,
|
||||||
|
animated: Boolean,
|
||||||
|
swipeable: Boolean
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
style() {
|
||||||
|
if (this.animated) {
|
||||||
|
return {
|
||||||
|
transform: `translate3d(${-1 * this.active * 100}%, 0, 0)`,
|
||||||
|
transitionDuration: `${this.duration}s`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
listeners() {
|
||||||
|
if (this.swipeable) {
|
||||||
|
return {
|
||||||
|
touchstart: this.touchStart,
|
||||||
|
touchmove: this.touchMove,
|
||||||
|
touchend: this.onTouchEnd,
|
||||||
|
touchcancel: this.onTouchEnd
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
// watch swipe touch end
|
||||||
|
onTouchEnd() {
|
||||||
|
const { direction, deltaX, active } = this;
|
||||||
|
|
||||||
|
/* istanbul ignore else */
|
||||||
|
if (direction === 'horizontal' && this.offsetX >= MIN_SWIPE_DISTANCE) {
|
||||||
|
console.log('on touchend', active, deltaX);
|
||||||
|
/* istanbul ignore else */
|
||||||
|
if (deltaX > 0 && active !== 0) {
|
||||||
|
this.$emit('change', active - 1);
|
||||||
|
} else if (deltaX < 0 && active !== this.count - 1) {
|
||||||
|
this.$emit('change', active + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
renderChildren() {
|
||||||
|
if (this.animated) {
|
||||||
|
return (
|
||||||
|
<div class={bem('track')} style={this.style}>
|
||||||
|
{this.slots()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.slots();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render(h) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
class={bem('content', { animated: this.animated })}
|
||||||
|
{...{ on: this.listeners }}
|
||||||
|
>
|
||||||
|
{this.renderChildren()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
@ -1,7 +1,6 @@
|
|||||||
import { use, isDef, suffixPx } from '../utils';
|
import { use, isDef, suffixPx } from '../utils';
|
||||||
import { scrollLeftTo } from './utils';
|
import { scrollLeftTo } from './utils';
|
||||||
import { on, off } from '../utils/dom/event';
|
import { on, off } from '../utils/dom/event';
|
||||||
import { TouchMixin } from '../mixins/touch';
|
|
||||||
import { ParentMixin } from '../mixins/relation';
|
import { ParentMixin } from '../mixins/relation';
|
||||||
import { BindEventMixin } from '../mixins/bind-event';
|
import { BindEventMixin } from '../mixins/bind-event';
|
||||||
import {
|
import {
|
||||||
@ -11,12 +10,12 @@ import {
|
|||||||
getScrollEventTarget
|
getScrollEventTarget
|
||||||
} from '../utils/dom/scroll';
|
} from '../utils/dom/scroll';
|
||||||
import Title from './Title';
|
import Title from './Title';
|
||||||
|
import Content from './Content';
|
||||||
|
|
||||||
const [sfc, bem] = use('tabs');
|
const [sfc, bem] = use('tabs');
|
||||||
|
|
||||||
export default sfc({
|
export default sfc({
|
||||||
mixins: [
|
mixins: [
|
||||||
TouchMixin,
|
|
||||||
ParentMixin('vanTabs'),
|
ParentMixin('vanTabs'),
|
||||||
BindEventMixin(function (bind, isBind) {
|
BindEventMixin(function (bind, isBind) {
|
||||||
this.bindScrollEvent(isBind);
|
this.bindScrollEvent(isBind);
|
||||||
@ -109,15 +108,6 @@ export default sfc({
|
|||||||
borderColor: this.color,
|
borderColor: this.color,
|
||||||
background: this.background
|
background: this.background
|
||||||
};
|
};
|
||||||
},
|
|
||||||
|
|
||||||
trackStyle() {
|
|
||||||
if (this.animated) {
|
|
||||||
return {
|
|
||||||
transform: `translate3d(${-1 * this.curActive * 100}%, 0, 0)`,
|
|
||||||
transitionDuration: `${this.duration}s`
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -181,22 +171,6 @@ export default sfc({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// watch swipe touch end
|
|
||||||
onTouchEnd() {
|
|
||||||
const { direction, deltaX, curActive } = this;
|
|
||||||
const minSwipeDistance = 50;
|
|
||||||
|
|
||||||
/* istanbul ignore else */
|
|
||||||
if (direction === 'horizontal' && this.offsetX >= minSwipeDistance) {
|
|
||||||
/* istanbul ignore else */
|
|
||||||
if (deltaX > 0 && curActive !== 0) {
|
|
||||||
this.setCurActive(curActive - 1);
|
|
||||||
} else if (deltaX < 0 && curActive !== this.children.length - 1) {
|
|
||||||
this.setCurActive(curActive + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// adjust tab position
|
// adjust tab position
|
||||||
onScroll() {
|
onScroll() {
|
||||||
const scrollTop = getScrollTop(window) + this.offsetTop;
|
const scrollTop = getScrollTop(window) + this.offsetTop;
|
||||||
@ -272,6 +246,7 @@ export default sfc({
|
|||||||
if (this.curActive !== null) {
|
if (this.curActive !== null) {
|
||||||
this.$emit('change', active, this.children[active].title);
|
this.$emit('change', active, this.children[active].title);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.curActive = active;
|
this.curActive = active;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -345,16 +320,6 @@ export default sfc({
|
|||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
||||||
let contentListeners;
|
|
||||||
if (this.swipeable) {
|
|
||||||
contentListeners = {
|
|
||||||
touchstart: this.touchStart,
|
|
||||||
touchmove: this.touchMove,
|
|
||||||
touchend: this.onTouchEnd,
|
|
||||||
touchcancel: this.onTouchEnd
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={bem([type])}>
|
<div class={bem([type])}>
|
||||||
<div
|
<div
|
||||||
@ -372,15 +337,16 @@ export default sfc({
|
|||||||
{this.slots('nav-right')}
|
{this.slots('nav-right')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class={bem('content', { animated })} {...{ on: contentListeners }}>
|
<Content
|
||||||
{animated ? (
|
count={this.children.length}
|
||||||
<div class={bem('track')} style={this.trackStyle}>
|
active={this.curActive}
|
||||||
{this.slots()}
|
animated={animated}
|
||||||
</div>
|
duration={this.duration}
|
||||||
) : (
|
swipeable={this.swipeable}
|
||||||
this.slots()
|
onChange={this.setCurActive}
|
||||||
)}
|
>
|
||||||
</div>
|
{this.slots()}
|
||||||
|
</Content>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user