mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
tabs组件支持滑动 (#52)
This commit is contained in:
parent
aaaba3888f
commit
2cc8f2ae5e
@ -4,7 +4,6 @@
|
|||||||
<van-tab title="选项二">内容二</van-tab>
|
<van-tab title="选项二">内容二</van-tab>
|
||||||
<van-tab title="选项三">内容三</van-tab>
|
<van-tab title="选项三">内容三</van-tab>
|
||||||
<van-tab title="选项四">内容四</van-tab>
|
<van-tab title="选项四">内容四</van-tab>
|
||||||
<van-tab title="选项五">内容五</van-tab>
|
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
|
|
||||||
</example-block><example-block title="基础用法">
|
</example-block><example-block title="基础用法">
|
||||||
@ -13,7 +12,6 @@
|
|||||||
<van-tab title="选项二">内容二</van-tab>
|
<van-tab title="选项二">内容二</van-tab>
|
||||||
<van-tab title="选项三">内容三</van-tab>
|
<van-tab title="选项三">内容三</van-tab>
|
||||||
<van-tab title="选项四">内容四</van-tab>
|
<van-tab title="选项四">内容四</van-tab>
|
||||||
<van-tab title="选项五">内容五</van-tab>
|
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
|
|
||||||
</example-block><example-block title="设置切换tab的动画时间">
|
</example-block><example-block title="设置切换tab的动画时间">
|
||||||
@ -23,13 +21,24 @@
|
|||||||
<van-tab title="选项三">内容三</van-tab>
|
<van-tab title="选项三">内容三</van-tab>
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
|
|
||||||
</example-block><example-block title="禁用tab">
|
</example-block><example-block title="多于4个tab时">
|
||||||
<van-tabs>
|
<van-tabs>
|
||||||
<van-tab title="选项三">内容一</van-tab>
|
<van-tab title="选项一">内容一</van-tab>
|
||||||
<van-tab title="选项二" disabled @disabled="popalert">内容二</van-tab>
|
<van-tab title="选项二">内容二</van-tab>
|
||||||
<van-tab title="选项三">内容三</van-tab>
|
<van-tab title="选项三">内容三</van-tab>
|
||||||
<van-tab title="选项四">内容四</van-tab>
|
<van-tab title="选项四">内容四</van-tab>
|
||||||
<van-tab title="选项五">内容五</van-tab>
|
<van-tab title="选项五">内容五</van-tab>
|
||||||
|
<van-tab title="选项六">内容六</van-tab>
|
||||||
|
<van-tab title="选项七">内容七</van-tab>
|
||||||
|
<van-tab title="选项八">内容八</van-tab>
|
||||||
|
</van-tabs>
|
||||||
|
|
||||||
|
</example-block><example-block title="禁用tab">
|
||||||
|
<van-tabs>
|
||||||
|
<van-tab title="选项一">内容一</van-tab>
|
||||||
|
<van-tab title="选项二" disabled @disabled="popalert">内容二</van-tab>
|
||||||
|
<van-tab title="选项三">内容三</van-tab>
|
||||||
|
<van-tab title="选项四">内容四</van-tab>
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
|
|
||||||
|
|
||||||
@ -40,7 +49,6 @@
|
|||||||
<van-tab title="选项二">内容二</van-tab>
|
<van-tab title="选项二">内容二</van-tab>
|
||||||
<van-tab title="选项三">内容三</van-tab>
|
<van-tab title="选项三">内容三</van-tab>
|
||||||
<van-tab title="选项四">内容四</van-tab>
|
<van-tab title="选项四">内容四</van-tab>
|
||||||
<van-tab title="选项五">内容五</van-tab>
|
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
|
|
||||||
</example-block><example-block title="自定义样式">
|
</example-block><example-block title="自定义样式">
|
||||||
@ -49,7 +57,6 @@
|
|||||||
<van-tab title="选项二" class="custom-pane">内容二</van-tab>
|
<van-tab title="选项二" class="custom-pane">内容二</van-tab>
|
||||||
<van-tab title="选项三" class="custom-pane">内容三</van-tab>
|
<van-tab title="选项三" class="custom-pane">内容三</van-tab>
|
||||||
<van-tab title="选项四" class="custom-pane">内容四</van-tab>
|
<van-tab title="选项四" class="custom-pane">内容四</van-tab>
|
||||||
<van-tab title="选项五" class="custom-pane">内容五</van-tab>
|
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
|
|
||||||
|
|
||||||
@ -60,7 +67,6 @@
|
|||||||
<van-tab title="选项二">内容二</van-tab>
|
<van-tab title="选项二">内容二</van-tab>
|
||||||
<van-tab title="选项三">内容三</van-tab>
|
<van-tab title="选项三">内容三</van-tab>
|
||||||
<van-tab title="选项四">内容四</van-tab>
|
<van-tab title="选项四">内容四</van-tab>
|
||||||
<van-tab title="选项五">内容五</van-tab>
|
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,7 +97,6 @@ export default {
|
|||||||
<van-tab title="选项二">内容二</van-tab>
|
<van-tab title="选项二">内容二</van-tab>
|
||||||
<van-tab title="选项三">内容三</van-tab>
|
<van-tab title="选项三">内容三</van-tab>
|
||||||
<van-tab title="选项四">内容四</van-tab>
|
<van-tab title="选项四">内容四</van-tab>
|
||||||
<van-tab title="选项五">内容五</van-tab>
|
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
@ -113,7 +112,6 @@ export default {
|
|||||||
<van-tab title="选项二">内容二</van-tab>
|
<van-tab title="选项二">内容二</van-tab>
|
||||||
<van-tab title="选项三">内容三</van-tab>
|
<van-tab title="选项三">内容三</van-tab>
|
||||||
<van-tab title="选项四">内容四</van-tab>
|
<van-tab title="选项四">内容四</van-tab>
|
||||||
<van-tab title="选项五">内容五</van-tab>
|
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
@ -132,6 +130,25 @@ export default {
|
|||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
#### 多于4个tab时
|
||||||
|
|
||||||
|
多于4个tab时,可以横向滚动tab。
|
||||||
|
|
||||||
|
:::demo 多于4个tab时
|
||||||
|
```html
|
||||||
|
<van-tabs>
|
||||||
|
<van-tab title="选项一">内容一</van-tab>
|
||||||
|
<van-tab title="选项二">内容二</van-tab>
|
||||||
|
<van-tab title="选项三">内容三</van-tab>
|
||||||
|
<van-tab title="选项四">内容四</van-tab>
|
||||||
|
<van-tab title="选项五">内容五</van-tab>
|
||||||
|
<van-tab title="选项六">内容六</van-tab>
|
||||||
|
<van-tab title="选项七">内容七</van-tab>
|
||||||
|
<van-tab title="选项八">内容八</van-tab>
|
||||||
|
</van-tabs>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
#### 禁用tab
|
#### 禁用tab
|
||||||
|
|
||||||
在对应的`van-tab`上设置`disabled`属性即可,如果需要监听禁用事件,可以监听`disabled`事件。
|
在对应的`van-tab`上设置`disabled`属性即可,如果需要监听禁用事件,可以监听`disabled`事件。
|
||||||
@ -139,11 +156,10 @@ export default {
|
|||||||
:::demo 禁用tab
|
:::demo 禁用tab
|
||||||
```html
|
```html
|
||||||
<van-tabs>
|
<van-tabs>
|
||||||
<van-tab title="选项三">内容一</van-tab>
|
<van-tab title="选项一">内容一</van-tab>
|
||||||
<van-tab title="选项二" disabled @disabled="popalert">内容二</van-tab>
|
<van-tab title="选项二" disabled @disabled="popalert">内容二</van-tab>
|
||||||
<van-tab title="选项三">内容三</van-tab>
|
<van-tab title="选项三">内容三</van-tab>
|
||||||
<van-tab title="选项四">内容四</van-tab>
|
<van-tab title="选项四">内容四</van-tab>
|
||||||
<van-tab title="选项五">内容五</van-tab>
|
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -169,7 +185,6 @@ export default {
|
|||||||
<van-tab title="选项二">内容二</van-tab>
|
<van-tab title="选项二">内容二</van-tab>
|
||||||
<van-tab title="选项三">内容三</van-tab>
|
<van-tab title="选项三">内容三</van-tab>
|
||||||
<van-tab title="选项四">内容四</van-tab>
|
<van-tab title="选项四">内容四</van-tab>
|
||||||
<van-tab title="选项五">内容五</van-tab>
|
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
@ -198,7 +213,6 @@ export default {
|
|||||||
<van-tab title="选项二" class="custom-pane">内容二</van-tab>
|
<van-tab title="选项二" class="custom-pane">内容二</van-tab>
|
||||||
<van-tab title="选项三" class="custom-pane">内容三</van-tab>
|
<van-tab title="选项三" class="custom-pane">内容三</van-tab>
|
||||||
<van-tab title="选项四" class="custom-pane">内容四</van-tab>
|
<van-tab title="选项四" class="custom-pane">内容四</van-tab>
|
||||||
<van-tab title="选项五" class="custom-pane">内容五</van-tab>
|
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@ -228,7 +242,6 @@ export default {
|
|||||||
<van-tab title="选项二">内容二</van-tab>
|
<van-tab title="选项二">内容二</van-tab>
|
||||||
<van-tab title="选项三">内容三</van-tab>
|
<van-tab title="选项三">内容三</van-tab>
|
||||||
<van-tab title="选项四">内容四</van-tab>
|
<van-tab title="选项四">内容四</van-tab>
|
||||||
<van-tab title="选项五">内容五</van-tab>
|
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -32,6 +32,7 @@ const showNextDialog = () => {
|
|||||||
initInstance();
|
initInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* istanbul ignore else */
|
||||||
if (!instance.value && dialogQueue.length > 0) {
|
if (!instance.value && dialogQueue.length > 0) {
|
||||||
currentDialog = dialogQueue.shift();
|
currentDialog = dialogQueue.shift();
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ let instance;
|
|||||||
const ImagePreviewConstructor = Vue.extend(ImagePreview);
|
const ImagePreviewConstructor = Vue.extend(ImagePreview);
|
||||||
|
|
||||||
const initInstance = () => {
|
const initInstance = () => {
|
||||||
|
/* istanbul ignore if */
|
||||||
if (Vue.prototype.$isServer) return;
|
if (Vue.prototype.$isServer) return;
|
||||||
instance = new ImagePreviewConstructor({
|
instance = new ImagePreviewConstructor({
|
||||||
el: document.createElement('div')
|
el: document.createElement('div')
|
||||||
@ -13,6 +14,7 @@ const initInstance = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var ImagePreviewBox = images => {
|
var ImagePreviewBox = images => {
|
||||||
|
/* istanbul ignore if */
|
||||||
if (Vue.prototype.$isServer) return;
|
if (Vue.prototype.$isServer) return;
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
initInstance();
|
initInstance();
|
||||||
|
@ -92,6 +92,7 @@ export default {
|
|||||||
const supportTouch = !Vue.prototype.$isServer && 'ontouchstart' in window;
|
const supportTouch = !Vue.prototype.$isServer && 'ontouchstart' in window;
|
||||||
const container = this.$refs.previewContainer;
|
const container = this.$refs.previewContainer;
|
||||||
|
|
||||||
|
/* istanbul ignore else */
|
||||||
if (supportTouch) {
|
if (supportTouch) {
|
||||||
let touchStartTime;
|
let touchStartTime;
|
||||||
|
|
||||||
@ -99,6 +100,7 @@ export default {
|
|||||||
touchStartTime = new Date();
|
touchStartTime = new Date();
|
||||||
});
|
});
|
||||||
container.addEventListener('touchend', () => {
|
container.addEventListener('touchend', () => {
|
||||||
|
/* istanbul ignore else */
|
||||||
if (new Date() - touchStartTime < 1500) {
|
if (new Date() - touchStartTime < 1500) {
|
||||||
this.value = false;
|
this.value = false;
|
||||||
}
|
}
|
||||||
|
@ -194,6 +194,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
end: () => {
|
end: () => {
|
||||||
|
/* istanbul ignore else */
|
||||||
if (this.isDragging) {
|
if (this.isDragging) {
|
||||||
this.isDragging = false;
|
this.isDragging = false;
|
||||||
|
|
||||||
|
46
packages/tab/src/swipe.js
Normal file
46
packages/tab/src/swipe.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import Vue from 'vue';
|
||||||
|
|
||||||
|
let isSwiping = false;
|
||||||
|
|
||||||
|
const supportTouch = !Vue.prototype.$isServer && 'ontouchstart' in window;
|
||||||
|
|
||||||
|
export default function(element, options) {
|
||||||
|
const moveFn = function(event) {
|
||||||
|
if (options.drag) {
|
||||||
|
options.drag(supportTouch ? event.changedTouches[0] || event.touches[0] : event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const endFn = function(event) {
|
||||||
|
if (!supportTouch) {
|
||||||
|
document.removeEventListener('mousemove', moveFn);
|
||||||
|
document.removeEventListener('mouseup', endFn);
|
||||||
|
}
|
||||||
|
|
||||||
|
isSwiping = false;
|
||||||
|
|
||||||
|
if (options.end) {
|
||||||
|
options.end(supportTouch ? event.changedTouches[0] || event.touches[0] : event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
element.addEventListener(supportTouch ? 'touchstart' : 'mousedown', function(event) {
|
||||||
|
if (isSwiping) return;
|
||||||
|
|
||||||
|
if (!supportTouch) {
|
||||||
|
document.addEventListener('mousemove', moveFn);
|
||||||
|
document.addEventListener('mouseup', endFn);
|
||||||
|
}
|
||||||
|
isSwiping = true;
|
||||||
|
|
||||||
|
if (options.start) {
|
||||||
|
options.start(supportTouch ? event.changedTouches[0] || event.touches[0] : event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (supportTouch) {
|
||||||
|
element.addEventListener('touchmove', moveFn);
|
||||||
|
element.addEventListener('touchend', endFn);
|
||||||
|
element.addEventListener('touchcancel', endFn);
|
||||||
|
}
|
||||||
|
};
|
@ -1,8 +1,26 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="van-tabs" :class="[`van-tabs--${type}`]">
|
<div class="van-tabs" :class="[`van-tabs--${type}`]">
|
||||||
|
<div class="van-tabs__nav-wrap" v-if="type === 'line' && tabs.length > 4">
|
||||||
|
<div class="van-tabs__swipe" ref="swipe">
|
||||||
|
<div class="van-tabs__nav van-tabs__nav--line">
|
||||||
|
<div class="van-tabs__nav-bar" :style="navBarStyle"></div>
|
||||||
<div
|
<div
|
||||||
|
v-for="(tab, index) in tabs"
|
||||||
|
:key="index"
|
||||||
|
class="van-tab"
|
||||||
|
:class="{'van-tab--active': index === curActive}"
|
||||||
|
ref="tabkey"
|
||||||
|
@click="handleTabClick(index, tab)"
|
||||||
|
>
|
||||||
|
{{ tab.title }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
class="van-tabs__nav"
|
class="van-tabs__nav"
|
||||||
:class="[`van-tabs__nav--${this.type}`, `van-tabs--col-${this.tabs.length}`]"
|
:class="[`van-tabs__nav--${this.type}`]"
|
||||||
>
|
>
|
||||||
<div class="van-tabs__nav-bar" :style="navBarStyle" v-if="type === 'line'"></div>
|
<div class="van-tabs__nav-bar" :style="navBarStyle" v-if="type === 'line'"></div>
|
||||||
<div
|
<div
|
||||||
@ -23,6 +41,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import swipe from './swipe';
|
||||||
|
import translateUtil from 'src/utils/transition';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'van-tabs',
|
name: 'van-tabs',
|
||||||
|
|
||||||
@ -48,13 +69,21 @@
|
|||||||
return {
|
return {
|
||||||
tabs: [],
|
tabs: [],
|
||||||
isReady: false,
|
isReady: false,
|
||||||
curActive: +this.active
|
curActive: +this.active,
|
||||||
|
isSwiping: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
active(val) {
|
active(val) {
|
||||||
this.curActive = +val;
|
this.curActive = +val;
|
||||||
|
},
|
||||||
|
|
||||||
|
curActive() {
|
||||||
|
/* istanbul ignore else */
|
||||||
|
if (this.tabs.length > 4) {
|
||||||
|
this.doOnValueChange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -72,12 +101,38 @@
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
width: offsetWidth,
|
width: offsetWidth,
|
||||||
transform: `translate3d(${offsetLeft}, 0px, 0px)`,
|
transform: `translate3d(${offsetLeft}, 0, 0)`,
|
||||||
transitionDuration: `${this.duration}s`
|
transitionDuration: `${this.duration}s`
|
||||||
};
|
};
|
||||||
|
},
|
||||||
|
swipeWidth() {
|
||||||
|
return this.$refs.swipe && this.$refs.swipe.getBoundingClientRect().width;
|
||||||
|
},
|
||||||
|
maxTranslate() {
|
||||||
|
/* istanbul ignore if */
|
||||||
|
if (!this.$refs.tabkey) return;
|
||||||
|
|
||||||
|
const lastTab = this.$refs.tabkey[this.tabs.length - 1];
|
||||||
|
const lastTabWidth = lastTab.offsetWidth;
|
||||||
|
const lastTabOffsetLeft = lastTab.offsetLeft;
|
||||||
|
|
||||||
|
return (lastTabOffsetLeft + lastTabWidth) - this.swipeWidth;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
// 页面载入完成
|
||||||
|
this.$nextTick(() => {
|
||||||
|
// 可以开始触发在computed中关于nav-bar的css动画
|
||||||
|
this.isReady = true;
|
||||||
|
this.initEvents();
|
||||||
|
|
||||||
|
if (this.tabs.length > 4) {
|
||||||
|
this.doOnValueChange();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
/**
|
/**
|
||||||
* tab点击事件
|
* tab点击事件
|
||||||
@ -93,15 +148,67 @@
|
|||||||
|
|
||||||
this.$emit('click', index);
|
this.$emit('click', index);
|
||||||
this.curActive = index;
|
this.curActive = index;
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
/**
|
||||||
// 页面载入完成
|
* 将当前value值转换为需要translate的值
|
||||||
this.$nextTick(() => {
|
*/
|
||||||
// 可以开始触发在computed中关于nav-bar的css动画
|
value2Translate(value) {
|
||||||
this.isReady = true;
|
/* istanbul ignore if */
|
||||||
});
|
if (!this.$refs.tabkey) return 0;
|
||||||
|
|
||||||
|
const tab = this.$refs.tabkey[value];
|
||||||
|
const maxTranslate = this.maxTranslate;
|
||||||
|
const tabWidth = tab.offsetWidth;
|
||||||
|
const tabOffsetLeft = tab.offsetLeft;
|
||||||
|
let translate = tabOffsetLeft + (tabWidth * 2.7) - this.swipeWidth;
|
||||||
|
if (translate < 0) {
|
||||||
|
translate = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1 * (translate > maxTranslate ? maxTranslate : translate);
|
||||||
|
},
|
||||||
|
|
||||||
|
initEvents() {
|
||||||
|
const el = this.$refs.swipe;
|
||||||
|
if (!el) return;
|
||||||
|
|
||||||
|
let swipeState = {};
|
||||||
|
|
||||||
|
swipe(el, {
|
||||||
|
start: event => {
|
||||||
|
swipeState = {
|
||||||
|
start: new Date(),
|
||||||
|
startLeft: event.pageX,
|
||||||
|
startTranslateLeft: translateUtil.getElementTranslate(el).left
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
drag: event => {
|
||||||
|
this.isSwiping = true;
|
||||||
|
|
||||||
|
swipeState.left = event.pageX;
|
||||||
|
const deltaX = swipeState.left - swipeState.startLeft;
|
||||||
|
const translate = swipeState.startTranslateLeft + deltaX;
|
||||||
|
|
||||||
|
/* istanbul ignore else */
|
||||||
|
if (translate > 0 || (translate * -1) > this.maxTranslate ) return;
|
||||||
|
|
||||||
|
translateUtil.translateElement(el, translate, null);
|
||||||
|
},
|
||||||
|
|
||||||
|
end: () => {
|
||||||
|
this.isSwiping = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
doOnValueChange() {
|
||||||
|
const value = +this.curActive;
|
||||||
|
const swipe = this.$refs.swipe;
|
||||||
|
|
||||||
|
translateUtil.translateElement(swipe, this.value2Translate(value), null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -5,27 +5,20 @@
|
|||||||
@b tabs {
|
@b tabs {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
@m col-2 {
|
@e nav-wrap {
|
||||||
.van-tab {
|
overflow: hidden;
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@m col-3 {
|
@e swipe {
|
||||||
|
user-select: none;
|
||||||
|
transition: transform ease .3s;
|
||||||
|
|
||||||
.van-tab {
|
.van-tab {
|
||||||
width: 33.33333333333333%;
|
flex: 0 0 22%;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@m col-4 {
|
.van-tabs__nav {
|
||||||
.van-tab {
|
overflow: visible;
|
||||||
width: 25%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@m col-5 {
|
|
||||||
.van-tab {
|
|
||||||
width: 20%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,16 +26,15 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition: transform .5s cubic-bezier(.645, .045, .355, 1);
|
transition: transform .5s cubic-bezier(.645, .045, .355, 1);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
@m line {
|
@m line {
|
||||||
height: 44px;
|
height: 44px;
|
||||||
background-color: $c-white;
|
|
||||||
|
.van-tab {
|
||||||
&::after {
|
&::after {
|
||||||
@mixin border-retina (top);
|
@mixin border-retina (top, bottom);
|
||||||
@mixin border-retina (bottom);
|
|
||||||
}
|
}
|
||||||
@b tabs-nav-bar {
|
|
||||||
display: block;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,14 +47,16 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
.van-tab {
|
.van-tab {
|
||||||
color: #666666;
|
color: #666;
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
border-right: 1px solid #666666;
|
border-right: 1px solid #666;
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
border-right: none;
|
border-right: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.van-tab--active {
|
&.van-tab--active {
|
||||||
background-color: #666666;
|
background-color: #666;
|
||||||
color: $c-white;
|
color: $c-white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,13 +76,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@b tab {
|
@b tab {
|
||||||
|
position: relative;
|
||||||
color: $c-black;
|
color: $c-black;
|
||||||
|
background-color: $c-white;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 44px;
|
line-height: 44px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
float: left;
|
flex: 1;
|
||||||
|
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||||
|
|
||||||
@m active {
|
@m active {
|
||||||
color: #FF4444;
|
color: #FF4444;
|
||||||
|
28
test/unit/components/more-tabs.vue
Normal file
28
test/unit/components/more-tabs.vue
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<template>
|
||||||
|
<van-tabs :active="active">
|
||||||
|
<van-tab title="选项一">内容一</van-tab>
|
||||||
|
<van-tab title="选项二">内容二</van-tab>
|
||||||
|
<van-tab title="选项三">内容三</van-tab>
|
||||||
|
<van-tab title="选项四">内容四</van-tab>
|
||||||
|
<van-tab title="选项五">内容五</van-tab>
|
||||||
|
<van-tab title="选项六">内容六</van-tab>
|
||||||
|
<van-tab title="选项七">内容七</van-tab>
|
||||||
|
<van-tab title="选项八">内容八</van-tab>
|
||||||
|
</van-tabs>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Tab from 'packages/tab';
|
||||||
|
import Tabs from 'packages/tabs';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
'van-tab': Tab,
|
||||||
|
'van-tabs': Tabs
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
active: [String, Number]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
@ -4,7 +4,6 @@
|
|||||||
<van-tab title="选项二">内容二</van-tab>
|
<van-tab title="选项二">内容二</van-tab>
|
||||||
<van-tab title="选项三" disabled>内容三</van-tab>
|
<van-tab title="选项三" disabled>内容三</van-tab>
|
||||||
<van-tab title="选项四">内容四</van-tab>
|
<van-tab title="选项四">内容四</van-tab>
|
||||||
<van-tab title="选项五">内容五</van-tab>
|
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import Dialog from 'packages/dialog';
|
import Dialog from 'packages/dialog';
|
||||||
|
import Vue from 'vue';
|
||||||
|
|
||||||
describe('Dialog', () => {
|
describe('Dialog', () => {
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -51,6 +52,6 @@ describe('Dialog', () => {
|
|||||||
document.querySelector('.van-dialog__cancel').click();
|
document.querySelector('.van-dialog__cancel').click();
|
||||||
expect(dialogAction).to.equal('cancel');
|
expect(dialogAction).to.equal('cancel');
|
||||||
done();
|
done();
|
||||||
}, 50);
|
}, 500);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -16,6 +16,7 @@ describe('ImagePreview', () => {
|
|||||||
|
|
||||||
it('create a image preview', (done) => {
|
it('create a image preview', (done) => {
|
||||||
ImagePreview([
|
ImagePreview([
|
||||||
|
'https://img.yzcdn.cn/upload_files/2017/03/15/FkubrzN7AgGwLlTeb1E89-T_ZjBg.png',
|
||||||
'https://img.yzcdn.cn/upload_files/2017/03/14/FmTPs0SeyQaAOSK1rRe1sL8RcwSY.jpeg',
|
'https://img.yzcdn.cn/upload_files/2017/03/14/FmTPs0SeyQaAOSK1rRe1sL8RcwSY.jpeg',
|
||||||
'https://img.yzcdn.cn/upload_files/2017/03/15/FvexrWlG_WxtCE9Omo5l27n_mAG_.jpeg'
|
'https://img.yzcdn.cn/upload_files/2017/03/15/FvexrWlG_WxtCE9Omo5l27n_mAG_.jpeg'
|
||||||
]);
|
]);
|
||||||
@ -40,6 +41,7 @@ describe('ImagePreview', () => {
|
|||||||
document.body.style.overflow = 'hidden';
|
document.body.style.overflow = 'hidden';
|
||||||
|
|
||||||
ImagePreview([
|
ImagePreview([
|
||||||
|
'https://img.yzcdn.cn/upload_files/2017/03/15/FkubrzN7AgGwLlTeb1E89-T_ZjBg.png',
|
||||||
'https://img.yzcdn.cn/upload_files/2017/03/14/FmTPs0SeyQaAOSK1rRe1sL8RcwSY.jpeg',
|
'https://img.yzcdn.cn/upload_files/2017/03/14/FmTPs0SeyQaAOSK1rRe1sL8RcwSY.jpeg',
|
||||||
'https://img.yzcdn.cn/upload_files/2017/03/15/FvexrWlG_WxtCE9Omo5l27n_mAG_.jpeg'
|
'https://img.yzcdn.cn/upload_files/2017/03/15/FvexrWlG_WxtCE9Omo5l27n_mAG_.jpeg'
|
||||||
]);
|
]);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import Tabs from 'packages/tabs';
|
import Tabs from 'packages/tabs';
|
||||||
import { mount } from 'avoriaz';
|
import { mount } from 'avoriaz';
|
||||||
import TabsTestComponent from '../components/tabs';
|
import TabsTestComponent from '../components/tabs';
|
||||||
|
import MoreTabsTestComponent from '../components/more-tabs';
|
||||||
|
|
||||||
describe('Tabs', () => {
|
describe('Tabs', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
@ -74,4 +75,75 @@ describe('Tabs', () => {
|
|||||||
|
|
||||||
expect(wrapper.style.transitionDuration != '').to.be.true;
|
expect(wrapper.style.transitionDuration != '').to.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('create a tabs greater then 4', (done) => {
|
||||||
|
wrapper = mount(MoreTabsTestComponent, {
|
||||||
|
attachToDocument: true
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.vm.$nextTick(() => {
|
||||||
|
const nTab = wrapper.find('.van-tab')[4];
|
||||||
|
nTab.trigger('click');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('create a tabs greater then 4 then click last tab', (done) => {
|
||||||
|
wrapper = mount(MoreTabsTestComponent, {
|
||||||
|
attachToDocument: true,
|
||||||
|
propsData: {
|
||||||
|
active: 7
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.vm.$nextTick(() => {
|
||||||
|
const nTab = wrapper.find('.van-tab')[6];
|
||||||
|
nTab.trigger('click');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test swipe', (done) => {
|
||||||
|
wrapper = mount(MoreTabsTestComponent, {
|
||||||
|
attachToDocument: true
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const nSwipe = wrapper.find('.van-tabs__swipe')[0];
|
||||||
|
|
||||||
|
const eventMouseObject = new window.Event('mousedown');
|
||||||
|
eventMouseObject.pageX = 200;
|
||||||
|
nSwipe.element.dispatchEvent(eventMouseObject);
|
||||||
|
|
||||||
|
const eventTouchObject = new window.Event('touchstart');
|
||||||
|
eventTouchObject.changedTouches = [{ pageX: 200 }];
|
||||||
|
nSwipe.element.dispatchEvent(eventTouchObject);
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const nSwipe = wrapper.find('.van-tabs__swipe')[0];
|
||||||
|
|
||||||
|
const eventMouseMoveObject = new window.Event('mousemove');
|
||||||
|
eventMouseMoveObject.pageX = 0;
|
||||||
|
document.dispatchEvent(eventMouseMoveObject);
|
||||||
|
|
||||||
|
const eventObject = new window.Event('touchmove');
|
||||||
|
eventObject.changedTouches = [{ pageX: 0 }];
|
||||||
|
nSwipe.element.dispatchEvent(eventObject);
|
||||||
|
|
||||||
|
// 结束滑动
|
||||||
|
const eventMouseUpObject = new window.Event('mouseup');
|
||||||
|
document.dispatchEvent(eventMouseUpObject);
|
||||||
|
const eventEndObject = new window.Event('touchend');
|
||||||
|
eventEndObject.changedTouches = [{}];
|
||||||
|
nSwipe.element.dispatchEvent(eventEndObject);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const nItem = wrapper.find('.van-tab')[0];
|
||||||
|
expect(nItem.hasClass('van-tab--active')).to.be.true;
|
||||||
|
|
||||||
|
done();
|
||||||
|
}, 1200);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -18,12 +18,4 @@ describe('Tag', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
it('create with wrong typeProps', () => {
|
|
||||||
wrapper = mount(Tag, {
|
|
||||||
propsData: {
|
|
||||||
type: 'wrong'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user