我有一个 Nuxt 2 应用程序,我正在尝试实现更原生的应用程序体验。
我正在使用模式来确保用户可以快速浏览应用程序并返回到他们之前所在的位置。
我在以“导航堆栈”方式处理多个模式时遇到一些困难,因为我需要能够将新 URL 推送到浏览器并允许用户使用浏览器后退按钮(特别是在移动操作系统、Android 或 iOS 中) 以及应用内导航。
目前我正在尝试使用
beforeRouteLeave
方法来拦截 Vue 路由器并显示模态并使用 window.history.pushState
更新 URL 这对于单个模态很好用,但是当我需要在顶部添加第二个模态并且用户使用浏览器的后退按钮,Vue 路由器启动并导航回索引并绕过我自己的导航堆栈数组。
我需要一种方法来跟踪用户的移动,然后像移动应用程序一样覆盖模式。
这是一支笔,展示了我当前的实现:
https://codesandbox.io/p/sandbox/elastic-ganguly-zu7jlv
我希望实现的例子:
如果我理解正确,您正试图在 Nuxt 2 应用程序中创建模态的“导航堆栈”,用户可以在其中使用应用内导航和浏览器的后退按钮通过模态向后导航。但是,当您尝试在第一个模式之上添加第二个模式时,您会遇到问题。
实现此类导航堆栈的一种方法是使用 Vuex 存储来跟踪模态的当前状态,包括它们的顺序以及它们当前是否显示。您可以使用 Vuex 操作将模态推送和弹出到堆栈上,并使用 Vuex getter 访问堆栈的当前状态。
这是一个如何工作的例子:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
modalStack: [], // array to store the modal stack
},
mutations: {
pushModal(state, modal) {
// add a new modal to the stack
state.modalStack.push(modal);
},
popModal(state) {
// remove the top modal from the stack
state.modalStack.pop();
},
},
actions: {
// action to show a new modal
showModal({ commit, state }, modal) {
// add the new modal to the stack
commit('pushModal', modal);
// update the URL with the new modal ID
const modalId = state.modalStack[state.modalStack.length - 1].id;
window.history.pushState({ modalId }, '', `/modal/${modalId}`);
},
// action to hide the top modal
hideModal({ commit, state }) {
// remove the top modal from the stack
commit('popModal');
// update the URL with the new top modal ID
const modalId = state.modalStack[state.modalStack.length - 1].id;
window.history.replaceState({ modalId }, '', `/modal/${modalId}`);
},
},
getters: {
// getter to get the current top modal
currentModal(state) {
return state.modalStack[state.modalStack.length - 1];
},
},
});
在这个例子中,
modalStack
数组用于存储当前堆栈的模态,最近添加的模态在数组的末尾。 pushModal
和 popModal
突变分别用于在堆栈中添加和删除模态。 showModal
和 hideModal
操作用于在堆栈中添加和删除模式,并使用 window.history
更新 URL。最后,currentModal
getter 用于获取当前的顶部模态。
ModalStack.vue
组件以使用 Vuex 商店:<template>
<div class="modal-stack">
<!-- loop through the modal stack and display each modal -->
<div v-for="(modal, index) in modals" :key="modal.id" class="modal-wrapper">
<div class="modal" :class="{ 'modal--visible': index === modals.length - 1 }">
<div class="modal-header">
<h2>{{ modal.title }}</h2>
<button @click="hideModal">Close</button>
</div>
<div class="modal-body">
<slot />
</div>
</div>
</div>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
export default {
computed: {
...mapGetters({
currentModal: 'currentModal