Javascript 停止或反向突出显示已单击的Vuetify v-tab项
我有一个VueJS/Vuetify应用程序,它的选项卡栏使用Javascript 停止或反向突出显示已单击的Vuetify v-tab项,javascript,vuejs2,tabs,vuetify.js,vuetify-tabs,Javascript,Vuejs2,Tabs,Vuetify.js,Vuetify Tabs,我有一个VueJS/Vuetify应用程序,它的选项卡栏使用v-tabs/v-tab组件在页面之间导航。我已经使用v-tab元素中的click事件实现了代码,该事件检查以确保用户单击另一个选项卡时没有未保存的内容,如果有,则使用v-dialog显示模式以提醒用户。如果用户选择继续,它将继续到所需的选项卡/组件。但是,如果用户在模式中选择了Cancel,页面将保留在原来的位置 以下是选项卡组件: <template> <div> <!-- Tabs --&
v-tabs
/v-tab
组件在页面之间导航。我已经使用v-tab
元素中的click
事件实现了代码,该事件检查以确保用户单击另一个选项卡时没有未保存的内容,如果有,则使用v-dialog
显示模式以提醒用户。如果用户选择继续,它将继续到所需的选项卡/组件。但是,如果用户在模式中选择了Cancel
,页面将保留在原来的位置
以下是选项卡组件:
<template>
<div>
<!-- Tabs -->
<v-tabs
color="secondary"
:value="currentTab"
>
<v-tab
v-for="(tab, i) in userTabs"
:key="i"
:href="tab.href"
@click="tabClick(tab.component, tab.link)"
:disabled="isDisabled(tab)"
>
{{ tab.title }}
</v-tab>
</v-tabs>
<BaseConfirmModal
:value="showUnsaved"
:title="unsavedContentTitle"
:text="unsavedContentText"
declineText="Cancel"
@clicked="unsavedModalConfirm"
/>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
import baseTabMixin from '@/components/mixins/workspace/baseTabMixin';
export default {
name: 'UserTabs',
data: () => ({
userTabs: [
{
title: 'General Info',
href: '#tab-general',
link: 'tab-general',
component: 'UserEdit',
},
{
title: 'Enrollments',
href: '#tab-enrollments',
link: 'tab-enrollments',
component: 'UserEnrollmentEdit',
},
{
title: 'Alerts',
href: '#tab-alerts',
link: 'tab-alerts',
component: 'UserAlertEdit',
},
{
title: 'Devices',
href: '#tab-devices',
link: 'tab-devices',
component: 'UserDeviceEdit',
},
],
}),
computed: {
...mapGetters('app', ['getStickyTenant', 'roleAtLeastTa', 'getUnsaved']),
...mapGetters('users', ['getCurrent']),
...mapGetters('tabs', {
currentTab: 'getSelected',
}),
},
methods: {
...mapActions('tabs', {
setCurrentTab: 'setSelected',
}),
isDisabled(item) {
if (item.component === 'UserEdit') {
return false;
}
if (item.component === 'UserDeviceEdit' && !this.roleAtLeastTa) {
return true;
}
return !this.getCurrent.userId;
},
},
mixins: [baseTabMixin],
};
</script>
问题与突出显示选项卡项有关。单击新选项卡时,滑块移动到新选项卡,新选项卡标题在调用单击事件(tabClick()
)之前以粗体显示。当我在我的模式中选择Cancel
时,它会将页面保留在原来的位置(如预期的那样),但单击的选项卡仍然高亮显示,滑块在下方,文本更粗体。由于所有这些都是在调用我的单击处理程序之前发生的,因此有没有办法a)在调用单击事件之前停止突出显示,或者b)将突出显示恢复到当前选项卡?链接到“工作”
请注意代码的关键部分:-
{{tab.title}}
async onTabChange(单击选项卡)
{
this.currentTab=单击的选项卡;
等待此消息。$nextTick();
如果(!this.allowTabChange)this.currentTab=this.previousTab;
else this.previousTab=this.currentTab;
}
v-tabs
组件使用内部模型来维护其状态,即哪个选项卡当前处于活动状态。使用:value
属性,我们可以设置初始活动选项卡。当用户单击其他选项卡时,内部模型将更新,从而使单击的选项卡高亮显示v-tabs
还会发出更改事件,通知父组件此更改。我们需要监听此事件并自行管理:value
变量,以维护父级中的状态。由于v-model
是对:value
和@change
的抽象,我们也可以使用它
要侦听此更改事件,请将@change
添加到v-tabs
。您可以将您在@单击时拥有的整个逻辑转换为@更改
,从而生成更干净的代码
为了防止选择下一个选项卡,我们需要使用一些复杂的代码,因为我们无法访问v-tabs
的内部模型。我们需要允许currentTab
临时更改为单击的选项卡,然后在$nextTick
中将其重置为previousTab
,即在Vue获取当前批更新之后。选项卡下方的突出显示出现在$nextTick
之后,因此它不会更改,因为此时我们已将:值
重置为以前的选项卡
如果您同意让突出显示临时移动到新选项卡,那么您需要做的就是将currentTab
更新到下一个选项卡的索引,突出显示将正常移动。然后,根据用户的决定,您可以将currentTab
设置为previousTab
以恢复更改,也可以使用currentTab
的新值更新previousTab
,即下一个选项卡。在这种情况下,$nextTick
黑客攻击是不必要的。多亏了@ParaBolt和他的代码笔的回答,我才得以工作。我的回答与他的略有不同,因为我的currentTab
存储在状态中,而不是组件,我还使用了filter
方法来获取组件的值,但结构是相同的
以下是mixin的重要部分:
data: () => ({
..
previousTab: '',
}),
methods: {
...mapActions('app', ['setUnsaved']),
async tabChange(newTab) {
this.setCurrentTab(newTab);
// We need to get the corresponding component value from the tabs array.
const newComponent = this.tabList.filter(tab => tab.link === newTab)[0].component;
// Stash these in case we need then in unsavedModalConfirm()
this.destTabComponent = newComponent;
this.destTabLink = newTab;
// Check to see if getUnsaved === true; if it is,
// set variable to display warning modal.
await this.$nextTick();
if (this.getUnsaved) {
this.setCurrentTab(this.previousTab);
this.showUnsaved = true;
} else {
// There is no unsaved content, so continue to the desired tab.
this.setCurrentTab(newTab);
this.$router.push({ name: newComponent });
}
},
unsavedModalConfirm(confirm) {
if (confirm) {
// User selected Continue from modal.
this.setCurrentTab(this.destTabLink);
this.$router.push({ name: this.destTabComponent });
this.setUnsaved(false);
} else {
// User selected Cancel
this.setCurrentTab(this.previousTab);
}
this.showUnsaved = false;
},
},
mounted() {
this.previousTab = this.currentTab;
},
每当我从模式中取消时,它都会停留在原来的位置,如果我选择继续,它会转到所需的选项卡。您尝试过@click.stop吗=“塔布克利。。。在您的选项卡组件上?@wheelmaker是的,我尝试了@click.stop
和@click.prevent
,但两者都没有起作用。有几个问题:1)currentTab
已通过mapGetters
定义为变量。那么,您是说覆盖它,还是将previousTab
设置为相同的值?2) 我无法真正将所有代码组合到@changed
事件中,因为我必须从所选的单个选项卡中传入组件
和链接
值。默认情况下,看起来我得到的是“link”值,而不是组件。有没有办法解决这个问题?嘿,我用一个代码笔例子更新了解释,希望它能清楚地表达我想要表达的意思。该笔还演示了如何获取与单击的选项卡相关联的数据以回答#2。由于该答案用于我的实际工作代码,因此该答案值得称赞。对于v-list/v-list-group
是否也是如此?我还必须为使用这些组件的侧边栏实现相同的功能?该逻辑应与实现值+更改/v-model功能的任何Vuetify组件配合使用。
data: () => ({
..
previousTab: '',
}),
methods: {
...mapActions('app', ['setUnsaved']),
async tabChange(newTab) {
this.setCurrentTab(newTab);
// We need to get the corresponding component value from the tabs array.
const newComponent = this.tabList.filter(tab => tab.link === newTab)[0].component;
// Stash these in case we need then in unsavedModalConfirm()
this.destTabComponent = newComponent;
this.destTabLink = newTab;
// Check to see if getUnsaved === true; if it is,
// set variable to display warning modal.
await this.$nextTick();
if (this.getUnsaved) {
this.setCurrentTab(this.previousTab);
this.showUnsaved = true;
} else {
// There is no unsaved content, so continue to the desired tab.
this.setCurrentTab(newTab);
this.$router.push({ name: newComponent });
}
},
unsavedModalConfirm(confirm) {
if (confirm) {
// User selected Continue from modal.
this.setCurrentTab(this.destTabLink);
this.$router.push({ name: this.destTabComponent });
this.setUnsaved(false);
} else {
// User selected Cancel
this.setCurrentTab(this.previousTab);
}
this.showUnsaved = false;
},
},
mounted() {
this.previousTab = this.currentTab;
},