2

有没有办法防止 v-tabs 在被点击时实际发生变化?

就我而言,我首先需要检查页面上的内容是否发生了变化,如果有,我想取消切换到另一个选项卡。

event.prevent 和 event.stop 都不会阻止 v-tabs 的变化: <v-tab @click.prevent.stop="..."> ... </v-tab>

目前我正在使用 awindow.requestAnimationFrame将选项卡索引重置为旧值。它完成了工作,但这对我来说感觉是一种非常讨厌的技术。

HTML:

    <v-tabs v-model="currentIndex">
        <v-tab v-for="(route, index) in list" :key="index" @change="handleTabChange(route, $event)" >
            {{ route.meta.title }}
        </v-tab>
    </v-tabs>

TS:

public handleTabChange(routeConf:RouteConfig):void {
    let currentIndex:number = this.currentIndex;
    window.requestAnimationFrame(() => {
            this.currentIndex = currentIndex;
            Store.app.router.goto(routeConf.name, null, this.$route.params);
            // Once the page actually changes this.currentIndex is set to the correct index..
        });
}
4

2 回答 2

7

v-tabs我通过在和之间使用单独的变量来解决这个问题v-tabs-items

<v-tabs v-model="tab" @change="onTabChange">
  <v-tab v-for="item in items" :key="item">
    {{ item }}
  </v-tab>
</v-tabs>

<v-tabs-items v-model="currentTab">
  <v-tab-item v-for="item in items" :key="item">
    <v-card>
      <v-card-text>{{ item }}</v-card-text>
    </v-card>
  </v-tab-item>
</v-tabs-items>
methods: {
  onTabChange() {
    if (/* reject */) {
      this.$nextTick(() => {
        this.tab = this.currentTab
      })
    } else {
      this.currentTab = this.tab
    }
  }
}

演示

另一种可能的解决方案是扩展v-tab更复杂但实际上可以覆盖行为的组件。

创建新文件my-tab.js

import { VTab } from 'vuetify/lib'

export default {
  extends: VTab,

  methods: {
    async click (e) {
      if (this.disabled) {
        e.preventDefault()
        return
      }

      // <-- your conditions
      let ok = await new Promise(resolve => {
        setTimeout(() => {
          resolve(false)
        }, 2000)
      })

      if (!ok) {
        this.$el.blur()
        return
      }
      // -->

      if (this.href &&
        this.href.indexOf('#') > -1
      ) e.preventDefault()

      if (e.detail) this.$el.blur()

      this.$emit('click', e)

      this.to || this.toggle()
    }
  }
}

原始源代码在这里。您还可以覆盖该render函数以更改样式。

然后将其用作普通组件:

<v-tabs v-model="tab">
  <my-tab v-for="item in items" :key="item">
    {{ item }}
  </my-tab>
</v-tabs>

<v-tabs-items v-model="tab">
  <v-tab-item v-for="item in items" :key="item">
    <v-card>
      <v-card-text
        >{{ item }} ipsum dolor sit amet, consectetur adipiscing elit, sed
        do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
        enim ad minim veniam, quis nostrud exercitation ullamco laboris
        nisi ut aliquip ex ea commodo consequat.</v-card-text
      >
    </v-card>
  </v-tab-item>
</v-tabs-items>
于 2020-01-05T22:33:52.093 回答
0

您应该在代码中遵循这种方式,这是一个可以帮助您的示例:

在 ts 文件中:

<template>
  <v-tabs v-model="activeTab">
     <v-tab v-for="tab in tabs" :key="tab.id" :to="tab.route">{{ tab.name }} 
     </v-tab>

     <v-tabs-items v-model="activeTab" @change="updateRouter($event)">
        <v-tab-item v-for="tab in tabs" :key="tab.id" :to="tab.route">
            <router-view />          
        </v-tab-item>
     </v-tabs-items>
   </v-tabs>
</template>

脚本:

export default {
data: () => ({
    activeTab: '',
    tabs: [
        {id: '1', name: 'Tab A', route: 'component-a'},
        {id: '2', name: 'Tab B', route: 'component-b'}
    ]
}),
methods: {
    updateRouter(val){
        this.$router.push(val)
    }
}

}

于 2019-10-17T07:15:06.813 回答