【问题标题】:Prevent Vuetify v-tabs from change防止 Vuetify v-tabs 发生变化
【发布时间】:2020-02-14 00:28:24
【问题描述】:

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

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

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

目前我正在使用window.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..
        });
}

【问题讨论】:

  • 而不是使用 click.prevent.stop 使用 click.stop.prevent
  • @chans 仍然无法阻止 v-tabs 的变化

标签: vue.js vuetify.js vuetify-tabs


【解决方案1】:

我通过在v-tabsv-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
    }
  }
}

Demo

另一种可能的解决方案是扩展 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()
    }
  }
}

原始源代码为here。您也可以重写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>

【讨论】:

  • 值得指出,这不适用于 async reject() 方法(例如异步确认对话框),视觉上它仍然会更改选项卡,然后将其更改回来。
  • @wondra 感谢您的指出。我更新我的答案。这是codesandbox。不幸的是,由于性能不佳,我无法运行它。我从本地复制的。我希望它会起作用。
【解决方案2】:

您应该在您的代码中遵循这种方式,这是对您有帮助的示例:

在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)
    }
}

}

【讨论】:

  • 我不明白这如何阻止标签更改。我也不使用 v-tabs-items;只是标签栏本身。
猜你喜欢
  • 1970-01-01
  • 2022-01-03
  • 2020-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-27
  • 2021-11-22
  • 1970-01-01
相关资源
最近更新 更多