VUE中,跳转页面之前判断并显示弹框组件

VUE中,跳转页面之前判断并显示弹框组件。
涉及到路由守卫、数据交互。有空我在完善,先直接给出代码
代码使用了 element plus、vuex

案例代码

路由文件

import { createRouter, createWebHistory } from 'vue-router';
import CommonEntry from '@/views/CommonEntry.vue';
import Home from '@/views/mobile/HomeView.vue';
import MainLayout from '@/views/mobile/MainLayout.vue';
import User from '@/views/mobile/UserView.vue';
import {useStore} from "vuex";

const routes = [
    {
        path: '/',
        name: 'commonEntry',
        component: CommonEntry,
    },
    {
        path: '/m/',
        name: 'homeMobile',
        component: MainLayout,
        children: [
            {
                path: '',
                name: 'home',
                component: Home,
            },
            {
                path: 'user',
                name: 'user',
                component: User,
                meta: { requiresAuth: true }
            }
        ]
    }
];

const router = createRouter({
    history: createWebHistory(process.env.BASE_URL),
    routes,
});

// 这里是关键
router.beforeEach((to, from, next) => {
    const store = useStore();

    if (to.matched.some(record => record.meta.requiresAuth && !store.getters['user/isAuthenticated'])) {
        if( from.name === undefined ) {  // 用户通过连接直接访问跳转到首页
            next('/');
        } else {
        	// 保存需要跳转的路由信息
            localStorage.setItem('wantedRoute', JSON.stringify({path: to.path, query: to.query, hash: to.hash}));
            // 显示登陆组件
            store.dispatch('authDialog/toggleLoginDialog', true);
            // 不进行下一步路由的跳转,由登陆组件中再次进行路由跳转
            next(false);
        }
    } else {
        next();
    }
});

export default router;

父组件MainLayout.vue




登陆组件LoginDialog.vue




利用uex来保存登陆状态 store.js

import {createStore} from "vuex";
import authDialog from './authDialog';

export default createStore({
    modules: {
        authDialog
    }
});

authDialog.js

const state = {
    isLoginDialogVisible: false,  // 登录对话框显示状态
    isRegisterDialogVisible: false,  // 注册对话框显示状态
};

const mutations = {
    setLoginDialogVisibility(state, visibility) {
        state.isLoginDialogVisible = visibility;
    },
    setRegisterDialogVisibility(state, visibility) {  // 控制注册对话框的显示状态
        state.isRegisterDialogVisible = visibility;
    },
};

const actions = {
    toggleLoginDialog({ commit }, visibility) {
        commit('setLoginDialogVisibility', visibility);
    },
    toggleRegisterDialog({ commit }, visibility) {  // 切换注册对话框的显隐
        commit('setRegisterDialogVisibility', visibility);
    },
};

const getters = {
    isLoginDialogVisible: (state) => state.isLoginDialogVisible,
    isRegisterDialogVisible: (state) => state.isRegisterDialogVisible,  // 获取注册对话框的显示状态
};

export default {
    namespaced: true,
    state,
    mutations,
    actions,
    getters,
};

全局方法:globalMixin.js

export default {
    data() {
        return {
            isSubmitting: false
        };
    },
    methods: {

        // 防止重复点击
        async preventMultipleSubmissions(action) {
            if (this.isSubmitting) {
                this.$message({
                    showClose: true,
                    message: this.$t('pleaseWait'),
                    type: 'warning'
                });
                return;
            }

            this.isSubmitting = true;
            try {
                await action();
            } catch (error) {
                this.$message({
                    showClose: true,
                    message: this.$t('operatorError'),
                    type: 'warning'
                });
            } finally {
                this.isSubmitting = false;
            }
        },
        
        // 登陆状态检查
        isAuthenticated() {
            return this.$store.state.user.userInfo !== null;
        }
    }
};

关键代码解释

让我来逐一解释你的问题:

问题 1: useStore 的作用和 store.dispatch 的使用

  1. useStore: 在 Vue 3 和 Vuex 4 中,useStore 是一个 Composition API 的方法,用于在组件内部访问 Vuex store。这是一种新的模式,用于取代在 Vue 2 中使用 this.$store 的方式。useStore 主要用于 setup 函数或其他 Composition API 函数中。

  2. 为什么不能直接通过方法名调用: Vuex 的 actionsmutations 需要通过 store 的 dispatchcommit 方法来调用,以保持状态管理的一致性和可追踪性。这是 Vuex 的设计哲学之一,旨在通过集中式存储管理应用的所有状态,并遵循特定的规则来更改状态。

  3. store.dispatch: 用于触发 Vuex store 中的 actionsactions 是可以包含任意异步操作的方法。在这个例子中,store.dispatch('authDialog/toggleLoginDialog', true) 会触发 authDialog 模块中的 toggleLoginDialog action,并传入 true 作为参数。

问题 2: commit 的作用和 mapActionsmapGetters 的使用

  1. commit: 在 Vuex 中,commit 用于触发 mutationsmutations 是同步函数,用于更改 Vuex store 中的状态。在这个例子中,commit('setLoginDialogVisibility', visibility) 会触发 setLoginDialogVisibility mutation,并传入 visibility 作为参数。

  2. ...mapActions...mapGetters: 这两个函数是 Vuex 提供的辅助函数,用于将 Vuex 的 actionsgetters 映射到组件的 methodscomputed 属性中。... 是 JavaScript 的展开运算符,用于将数组或对象展开到另一个数组或对象中。在这个例子中,...mapActions('authDialog', ['toggleLoginDialog', 'toggleRegisterDialog'])authDialog 模块的 toggleLoginDialogtoggleRegisterDialog actions 映射到组件的方法中,而 ...mapGetters 类似地将 getters 映射到计算属性中。

问题 3: @update: 的作用和 $emit 的使用

  1. @update:: 是 Vue 中的一个事件监听修饰符,用于监听子组件触发的更新事件。在这个例子中,@update:dialogVisible="handleLoginDialogVisibilityChange" 监听 LoginDialog 组件触发的 update:dialogVisible 事件,并调用 handleLoginDialogVisibilityChange 方法来响应该事件。

  2. this.$emit: 在 Vue 组件中,this.$emit 用于子组件向父组件发送事件。this.$emit('update:dialogVisible', value) 就是 LoginDialogRegisterDialog 组件向父组件发送 update:dialogVisible 事件,并传递 value 作为参数。

  3. 父子数据交互: 是的,@update: 修饰符和 this.$emit 一起工作,实现了父子组件之间的数据交互。子组件通过 $emit 发出事件,父组件通过监听这些事件来响应变化。

这种模式是 Vue 组件间通信的常用方法之一,有助于保持数据的单向流动,从而使得状态管理更加清晰和可维护。

你可能感兴趣的:(vue.js,前端,javascript)