停止或反向突出显示已单击的 Vuetify v-tab 项目
Stop or reverse highlighting of clicked Vuetify v-tab item
我有一个 VueJS/Vuetify 应用程序,它的标签栏使用 v-tabs
/v-tab
组件在页面之间导航。我已经使用 v-tab
元素中的 click
事件实现了代码,该代码检查以确保当用户单击另一个选项卡时没有未保存的内容,如果有,则使用 [=17 显示模态=] 提醒用户。如果用户选择继续,它将继续到所需的 tab/component。但是,如果用户 selects 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>
和引用的 baseTabMixin
:
import { mapGetters, mapActions } from 'vuex';
const baseTabMixin = {
data: () => ({
showUnsaved: false,
unsavedContentTitle: 'Unsaved Changes',
unsavedContentText: 'You have made changes to this page that are not saved. Do you wish to continue?',
destTabComponent: '',
destTabLink: '',
}),
components: {
BaseConfirmModal: () => import('@/components/base/BaseConfirmModal'),
},
computed: {
...mapGetters('app', ['getUnsaved']),
},
methods: {
...mapActions('app', ['setUnsaved']),
tabClick(component, tab) {
// Check to see if getUnsaved === true; if it is,
// set variable to display warning modal.
if (this.getUnsaved) {
this.showUnsaved = true;
} else {
// There is no unsaved content, so continue to the desired tab.
this.destTabComponent = component;
this.destTabLink = tab;
this.setCurrentTab(tab);
this.$router.push({ name: component });
}
},
unsavedModalConfirm(confirm) {
if (confirm) {
this.setCurrentTab(this.destTabLink);
this.$router.push({ name: this.destTabComponent });
}
this.showUnsaved = false;
},
},
};
export default baseTabMixin;
问题与选项卡项目突出显示有关。单击新选项卡时,滑块将移动到新选项卡,并且在调用单击事件(在本例中为 tabClick()
)之前,新选项卡标题会加粗。当我在我的模式中 select Cancel
时,它会将页面留在原处(如预期的那样),但单击的选项卡仍然突出显示,下方的滑块和更粗的文本。由于这一切都发生在我的点击处理程序被调用之前,有没有办法 a) 在调用点击事件之前停止突出显示,或者 b) 将突出显示反转回当前选项卡?
Link 工作 pen.
注意代码的关键部分:-
<v-tabs :value="currentTab" @change="onTabChange">
<v-tab v-for="(tab, i) in tabs" :key="i">{{tab.title}}</v-tab>
</v-tabs>
async onTabChange(clickedTab)
{
this.currentTab = clickedTab;
await this.$nextTick();
if (!this.allowTabChange) this.currentTab = this.previousTab;
else this.previousTab = this.currentTab;
}
v-tabs
组件使用内部模型来维护其状态,即哪个选项卡当前处于活动状态。使用 :value
属性,我们可以设置一个初始活动选项卡。当用户单击不同的选项卡时,内部模型会更新,导致单击的选项卡突出显示。 v-tabs
还会发出一个更改事件来通知父组件此更改。我们需要监听此事件并自行管理 :value
变量以维护父级中的状态。由于 v-model
是 :value
和 @change
的抽象,我们也可以使用它。
要侦听此更改事件,请将 @change
添加到 v-tabs
。您可以将 @click
中的整个逻辑转移到 @change
中,从而使代码更清晰。
为了防止选择下一个选项卡,我们需要使用一些棘手的代码,因为我们无法访问 v-tabs
的内部模型。我们需要允许 currentTab
临时更改为单击的选项卡,然后在 $nextTick
中将其重置为 previousTab
,即在 Vue 获取当前批次更新之后。选项卡下方的突出显示出现在 $nextTick
之后,因此它不会更改,因为届时我们已将 :value
重置为 previousTab
。
如果您可以让突出显示暂时转移到新标签,那么您需要做的就是更新 currentTab
到下一个标签的索引,突出显示将照常转移。然后根据用户的决定,您可以将 currentTab
设置为 previousTab
以恢复更改,或者您可以使用 currentTab
的新值更新 previousTab
即下一个选项卡.在这种情况下,$nextTick
hack 是不必要的。
多亏了@ParaBolt 和他的 CodePen 的回答,我才开始工作。我的回答和他的略有不同,因为我的 currentTab
存储在状态中,而不是组件中,我也使用了 filter
方法来获取 component
值,但结构是相同的。
以下是 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;
},
每当我从模式中取消时,它只会停留在原处,如果我选择继续,它会转到所需的选项卡。
我有一个 VueJS/Vuetify 应用程序,它的标签栏使用 v-tabs
/v-tab
组件在页面之间导航。我已经使用 v-tab
元素中的 click
事件实现了代码,该代码检查以确保当用户单击另一个选项卡时没有未保存的内容,如果有,则使用 [=17 显示模态=] 提醒用户。如果用户选择继续,它将继续到所需的 tab/component。但是,如果用户 selects 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>
和引用的 baseTabMixin
:
import { mapGetters, mapActions } from 'vuex';
const baseTabMixin = {
data: () => ({
showUnsaved: false,
unsavedContentTitle: 'Unsaved Changes',
unsavedContentText: 'You have made changes to this page that are not saved. Do you wish to continue?',
destTabComponent: '',
destTabLink: '',
}),
components: {
BaseConfirmModal: () => import('@/components/base/BaseConfirmModal'),
},
computed: {
...mapGetters('app', ['getUnsaved']),
},
methods: {
...mapActions('app', ['setUnsaved']),
tabClick(component, tab) {
// Check to see if getUnsaved === true; if it is,
// set variable to display warning modal.
if (this.getUnsaved) {
this.showUnsaved = true;
} else {
// There is no unsaved content, so continue to the desired tab.
this.destTabComponent = component;
this.destTabLink = tab;
this.setCurrentTab(tab);
this.$router.push({ name: component });
}
},
unsavedModalConfirm(confirm) {
if (confirm) {
this.setCurrentTab(this.destTabLink);
this.$router.push({ name: this.destTabComponent });
}
this.showUnsaved = false;
},
},
};
export default baseTabMixin;
问题与选项卡项目突出显示有关。单击新选项卡时,滑块将移动到新选项卡,并且在调用单击事件(在本例中为 tabClick()
)之前,新选项卡标题会加粗。当我在我的模式中 select Cancel
时,它会将页面留在原处(如预期的那样),但单击的选项卡仍然突出显示,下方的滑块和更粗的文本。由于这一切都发生在我的点击处理程序被调用之前,有没有办法 a) 在调用点击事件之前停止突出显示,或者 b) 将突出显示反转回当前选项卡?
Link 工作 pen.
注意代码的关键部分:-
<v-tabs :value="currentTab" @change="onTabChange">
<v-tab v-for="(tab, i) in tabs" :key="i">{{tab.title}}</v-tab>
</v-tabs>
async onTabChange(clickedTab)
{
this.currentTab = clickedTab;
await this.$nextTick();
if (!this.allowTabChange) this.currentTab = this.previousTab;
else this.previousTab = this.currentTab;
}
v-tabs
组件使用内部模型来维护其状态,即哪个选项卡当前处于活动状态。使用 :value
属性,我们可以设置一个初始活动选项卡。当用户单击不同的选项卡时,内部模型会更新,导致单击的选项卡突出显示。 v-tabs
还会发出一个更改事件来通知父组件此更改。我们需要监听此事件并自行管理 :value
变量以维护父级中的状态。由于 v-model
是 :value
和 @change
的抽象,我们也可以使用它。
要侦听此更改事件,请将 @change
添加到 v-tabs
。您可以将 @click
中的整个逻辑转移到 @change
中,从而使代码更清晰。
为了防止选择下一个选项卡,我们需要使用一些棘手的代码,因为我们无法访问 v-tabs
的内部模型。我们需要允许 currentTab
临时更改为单击的选项卡,然后在 $nextTick
中将其重置为 previousTab
,即在 Vue 获取当前批次更新之后。选项卡下方的突出显示出现在 $nextTick
之后,因此它不会更改,因为届时我们已将 :value
重置为 previousTab
。
如果您可以让突出显示暂时转移到新标签,那么您需要做的就是更新 currentTab
到下一个标签的索引,突出显示将照常转移。然后根据用户的决定,您可以将 currentTab
设置为 previousTab
以恢复更改,或者您可以使用 currentTab
的新值更新 previousTab
即下一个选项卡.在这种情况下,$nextTick
hack 是不必要的。
多亏了@ParaBolt 和他的 CodePen 的回答,我才开始工作。我的回答和他的略有不同,因为我的 currentTab
存储在状态中,而不是组件中,我也使用了 filter
方法来获取 component
值,但结构是相同的。
以下是 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;
},
每当我从模式中取消时,它只会停留在原处,如果我选择继续,它会转到所需的选项卡。