123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- <template>
- <view class="component-view-tab">
- <scroll-nav :fixed="tabFix" ref="scrollNav" :background="background" :scrollData="scrollData" :activeKey.sync="activeKey" @change="changeTab" @tabClick="tabClick" :animate="animate" :height="height" :line="line" :font="font"></scroll-nav>
- <view class="scroll-view">
- <view :class="['tab-wrapper',{animate}]" :style="[{left:tabview.left+'px'}]">
- <view class="tab" v-for="(item,key) in scrollData" :key="key">
- <view v-if="forceRender ? true :activeKey === key" class="tab-content" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd($event,key)">
- <slot name="{{item.slot}}"/>
- </view>
- </view>
- </view>
- </view>
- </view>
- </template>
- <script>
- import scrollNav from './ScrollNav';
- export default {
- components: {scrollNav},
- props: {
- navData:{
- default:()=>[],
- type:Array
- },
- value:{
- default:0,
- type:Number
- },
- animate:{
- default:true,
- type:Boolean
- },
- scrollThreshold:{
- default:50,
- type:Number
- },
- height:{
- default:'70rpx',
- type:String
- },
- line:Object,
- font:Object,
- background:String,
- forceRender:{
- default:false,
- type:Boolean
- },
- tabFix:Object
- },
- // mixins: [require('@/components/mixins/Component').default],
- data() {
- return {
- tabview:{
- left:0
- },
- scrollData:[],
- activeKey:0
- };
- },
- emits:['change','update:value','tabClick','rendered'],
- created() {
- },
- mounted() {},
- unmounted() {},
- computed: {
- },
- watch: {
- navData:{
- handler(n){
- this.scrollData = n;
- this.$nextTick(this.resizeStyle);
- },
- deep:true,
- immediate:true
- },
- value:{
- handler(n){
- this.setPosition(n,'set');
- },
- deep:true,
- immediate:true
- }
- },
- methods: {
- async init(){
- },
- load(){},
- $document(self, select, cfg) {
- return new Promise((res, rej) => {
- if (!self || !select) rej('$document:params error');
- uni.createSelectorQuery().in(self).select(select).fields(Object.assign({
- id: true,
- dataset: true,
- rect:true,
- size: true,
- scrollOffset: true,
- context:true
- },cfg),data=>res(data)).exec();
- })
- },
- async changeTab(e){
- await this.setPosition(e);
- },
- tabClick(e){
- this.$emit('tabClick',this.handleItem(e));
- },
- handleItem(e){
- return {
- index:e,
- item:this.scrollData[e]
- }
- },
- touchStart(e){
- if(this.locked) return;
- var client = e.touches[0];
- Object.assign(this,{
- client,
- position:[client]
- });
- },
- touchMove(e){
- if(!this.position) return;
- var client = e.touches[0];
- if(Math.abs(client.clientY - this.client.clientY) < 25){
- this.position.push(client);
- const
- positions = this.position.map(item=>Object.assign({},item)),
- sorted = positions.sort((a,b)=>a.clientX - b.clientX);
- if(sorted[0].clientX !== client.clientX && sorted.slice(-1)[0].clientX !== client.clientX){
- this.clearPosition();
- }
- }else{
- this.clearPosition();
- }
- },
- async touchEnd(e,key){
- var
- positions = this.position,
- act;
- if(positions){
- var move = positions.slice(-1)[0].clientX - positions[0].clientX;
- if(Math.abs(move) < this.scrollThreshold) return;
- act = move > 0 ? 1 : -1;
- var changeKey = key - act;
- if(changeKey < 0 || changeKey > this.navData.length - 1) return;
- await this.setPosition(changeKey);
- this.clearPosition();
- }
- },
- async setPosition(key,act){
- this.locked = true;
- switch(act){
- case 'set':
- break;
- default:
- this.$emit('update:value',key);
- this.$emit('change',this.handleItem(key));
- }
- this.activeKey = key;
- try{
- !this.itemWidth && (this.itemWidth = (await this.$document(this,'.tab')).width);
- this.tabview.left = -key * this.itemWidth;
- }catch(e){}
- await new Promise(r=>setTimeout(r,300));
- this.locked && (this.locked = false);
- },
- clearPosition(){
- this.position = null;
- },
- resizeStyle(){
- this.$refs.scrollNav.changeStyle(this.activeKey);
- }
- },
- directives: {},
- errorCaptured() {},
- renderTracked() {},
- renderTriggered() {},
- };
- </script>
- <style lang='stylus'>
- .component-view-tab
- width 100%;overflow auto;
- .scroll-view
- overflow hidden;width 100%;max-width 100%;
- .tab-wrapper
- width 100%;display flex;felx-wrap:nowrap;position relative;
- &.animate
- transition all .3s;
- .tab
- min-width 100%;max-width 100%;
- .tab-content
- overflow hidden;width 100%;height 100%;
- </style>
|