Vue3路由守卫、vuex的使用、vuex模块化拆分、vite中自动导入模块文件

news2025/7/29 14:12:41

文章目录

  • 1. 路由守卫
  • 2. vuex的使用
    • 2.1 基本使用
    • 2.2 模块化拆分
      • 方式一
      • 方式二
      • 方式三
  • 3. 在vite中自动导入模块文件


1. 路由守卫

vue3 中的导航守卫与 vue2 中的基本一致,不同的地方在于,vue3 中导航守卫取消了 next 参数,而是通过返回 false 来取消路由跳转。

以前置路由守卫为例,结合 sessionStorage 实现获取 token 值之后跳转到后台管理页面。

配置路由及守卫:

// vue-router中提供3种的路由模式
import { createWebHistory, createRouter } from 'vue-router'

const routes = [
  {
    path: '/login',
    component: () => import('@/views/login.vue')
  },
  {
    path: '/admin',
    component: () => import('@/views/admin.vue'),
    meta: {
      isLogin: true
    }
  }
] 

const router = createRouter({
  // 路由的模式
  history: createWebHistory(),
  // 路由规则
  routes
})

// 全局前置守卫
router.beforeEach((to, from) => {
  // 验证指定的页面无须登录就可以访问
  // 1.可以通过path路由来区别
  // 2.meta来完成区别
  // console.log('前置全局守卫', to.path);
  // console.log('前置全局守卫', to.meta.isLogin);
  // 如果此页面需要登录才能访问到,就需要来判断当前的本地存储中是否有token
  if (!to.meta.isLogin) {
    return true
  }
  // 如下的页面一定要求用户登录才能访问到
  if (!sessionStorage.getItem('token')) {
    // 跳转到登录页
    // return '/login'
    // 跳转后不能回退
    return { path: '/login', replace: true }
  }

  return true
})

export default router

mock 假数据:

import Mockjs from 'mockjs'

const mockData = [
  {
    url: '/api/login',
    method: 'post',
    response: () => ({
      code: 0,
      msg: 'ok',
      data: {
        uid: 1000,
        nickname: '张三',
        token: 'afewlfjewlfjewlfejlfejl;fejlf;e'
      }
    })
  }
]

export default mockData

登录页:

<template>
  <div>
    <h3>登录页面</h3>
    <div>
      <input type="text" v-model="username" />
    </div>
    <div>
      <input type="text" v-model="password" />
    </div>
    <div>
      <button @click="doLogin">进入系统</button>
    </div>
  </div>
</template>

<script setup>
import { reactive, toRefs } from 'vue'
import { useRouter } from 'vue-router'
import { doLoginApi } from '@/api/userApi'

const router = useRouter()

const state = reactive({
  username: '',
  password: ''
})
const { username, password } = { ...toRefs(state) }

// 登录成功
const doLogin = async () => {
  let ret = await doLoginApi(state)
  let token = ret.data.token
  sessionStorage.setItem('token', token)
  router.replace('/admin')
}
</script>

<style lang="scss" scoped>

</style>

后台管理页:

<template>
  <div>
    <h3>后台管理</h3>
  </div>
</template>

<script setup>

</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

2. vuex的使用

2.1 基本使用

安装:

yarn add vuex

使用:

首先为 vuex 创建 store 目录(store/index.js):

import { createStore } from 'vuex'

// const store = createStore({
//   state: {
//     num: 100
//   }
// })

// 如果你现在用的是基于vue的服务器端渲染,此时一定要写成回调函数方案
const store = createStore({
  state: () => ({
    num: 100
  }),
  mutations: {
    setNum(state, payload) {
      state.num += payload
    }
  },
  actions: {
    asyncSetNum({ commit }, payload) {
      setTimeout(() => {
        commit('setNum', payload)
      }, 1000);
    }
  }
})

export default store

在入口文件(main.js)处引入 vuex:

// 创建vue入口程序,由原来的类实例,变成现在的函数方式,为了更好在打包时优化代码
import { createApp } from 'vue'
// 根组件
import App from './App.vue'
// 路由
import router from './router'
// vuex
import store from './store'

import createGlobalComponent from './components'
import globalProperties from './config/globalProperties'

// 实例化一个Vue顶层组件
// const app = createApp(App)

// 创建全局组件
// // createGlobalComponent(app)
// app.use(createGlobalComponent)
// app.use(globalProperties)
// // 路由
// app.use(router)
// // vuex
// app.use(store)
// app.mount('#app')

// 工作中常用写法:
createApp(App)
  .use(createGlobalComponent)
  .use(globalProperties)
  .use(router)
  .use(store)
  .mount('#app')

关于页面:

<template>
  <div>
    <h3>关于页面 -- {{ num }}</h3>
    <button @click="setNum">++同步++</button>
    <button @click="asyncSetNum">++异步++</button>
  </div>
</template>

<script setup>
import { computed } from 'vue'
// vuex提供hook函数
import { useStore } from 'vuex'
const store = useStore()

const num = computed(() => store.state.num)

const setNum = () => {
  store.commit('setNum', 1)
}

const asyncSetNum = () => {
  store.dispatch('asyncSetNum', 2)
}
</script>

<style lang="scss" scoped></style>

在这里插入图片描述

2.2 模块化拆分

方式一

store/modules/count.js:

export default {
  // 开启强制命名空间
  namespaced: true,
  state: () => ({
    num: 100
  }),
  mutations: {
    setNum(state, payload) {
      state.num += payload
    }
  },
  actions: {
    asyncSetNum({ commit }, payload) {
      setTimeout(() => {
        commit('setNum', payload)
      }, 1000);
    }
  }
}

store/modules/user.js:

export default {
  // 开启强制命名空间
  namespaced: true,
  state: () => ({
    uid: 0,
    nickname: '',
    token: ''
  }),
  mutations: {
    login(state, payload) {
      state.uid = payload.uid
      state.nickname = payload.nickname
      state.token = payload.token
      sessionStorage.setItem('token', payload.token)
    }
  },
  actions: {
  }
}

store/index.js:

import { createStore, useStore } from 'vuex'

import count from './modules/count'
import user from './modules/user'

// 如果你现在用的是基于vue的服务器端渲染,此时一定要写成回调函数方案
const store = createStore({
  modules: {
    count,
    user
  }
})

export default store

关于页面:

<template>
  <div>
    <h3>关于页面 -- {{ num }}</h3>
    <button @click="setNum">++同步++</button>
    <button @click="asyncSetNum">++异步++</button>
  </div>
</template>

<script setup>
import { computed } from 'vue'
// vuex提供hook函数
// 方式一导入
import { useStore } from 'vuex'
const store = useStore()

const num = computed(() => store.state.count.num)

const setNum = () => {
  store.commit('count/setNum', 1)
}

const asyncSetNum = () => {
  store.dispatch('count/asyncSetNum', 2)
}
</script>

<style lang="scss" scoped></style>

登录页面:

<template>
  <div>
    <h3>登录页面</h3>
    <div>
      <input type="text" v-model="username" />
    </div>
    <div>
      <input type="text" v-model="password" />
    </div>
    <div>
      <button @click="doLogin">进入系统</button>
    </div>
  </div>
</template>

<script setup>
import { reactive, toRefs } from 'vue'
import { useRouter } from 'vue-router'
import { doLoginApi } from '@/api/userApi'

//方式一导入
import { useStore } from 'vuex'
const store = useStore()

const router = useRouter()

const state = reactive({
  username: '',
  password: ''
})
const { username, password } = { ...toRefs(state) }

// 登录成功
const doLogin = async () => {
  let ret = await doLoginApi(state)
  let token = ret.data.token
  sessionStorage.setItem('token', token)
  router.replace('/admin')
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

在这里插入图片描述

方式二

对 store 的入口文件中模块的导出作修改(对 useStore 做二次封装后导出)、对登录页面模块的导入作修改。

store/index.js:

import { createStore, useStore } from 'vuex'

import count from './modules/count'
import user from './modules/user'

// 如果你现在用的是基于vue的服务器端渲染,此时一定要写成回调函数方案
const store = createStore({
  modules: {
    count,
    user
  }
})

// 方式二导出
export const useUserStateStore = () => {
  let store = useStore()
  return [store.state.user, store.commit, store.dispatch]
}

export default store

登录页面:

<template>
  <div>
    <h3>登录页面</h3>
    <div>
      <input type="text" v-model="username" />
    </div>
    <div>
      <input type="text" v-model="password" />
    </div>
    <div>
      <button @click="doLogin">进入系统</button>
    </div>
  </div>
</template>

<script setup>
import { reactive, toRefs } from 'vue'
import { useRouter } from 'vue-router'
import { doLoginApi } from '@/api/userApi'

//方式二导入
import { useUserStateStore } from '@/store'
const [userState, commit] = useUserStateStore()

const router = useRouter()

const state = reactive({
  username: '',
  password: ''
})
const { username, password } = { ...toRefs(state) }

// 登录成功
const doLogin = async () => {
  let ret = await doLoginApi(state)
  let token = ret.data.token
  commit('user/login', ret.data)
  router.replace('/admin')
}
</script>

<style lang="scss" scoped>

</style>

方式三

在方式二的基础上,将 store/index.js 文件中的方法,拆分开导入。

store/index.js:

import { createStore, useStore } from 'vuex'

import count from './modules/count'
import user from './modules/user'

// 如果你现在用的是基于vue的服务器端渲染,此时一定要写成回调函数方案
const store = createStore({
  modules: {
    count,
    user
  }
})

export const useUserState = () => {
  let store = useStore()
  return store.state.user
}

export const useCommit = () => {
  let store = useStore()
  return store.commit
}

export const useDispatch = () => {
  let store = useStore()
  return store.dispatch
}

export default store

登录页面:

<template>
  <div>
    <h3>登录页面</h3>
    <div>
      <input type="text" v-model="username" />
    </div>
    <div>
      <input type="text" v-model="password" />
    </div>
    <div>
      <button @click="doLogin">进入系统</button>
    </div>
  </div>
</template>

<script setup>
import { reactive, toRefs } from 'vue'
import { useRouter } from 'vue-router'
import { doLoginApi } from '@/api/userApi'

const router = useRouter()

const state = reactive({
  username: '',
  password: ''
})
const { username, password } = { ...toRefs(state) }

// 登录成功
const doLogin = async () => {
  let ret = await doLoginApi(state)
  let token = ret.data.token
  commit('user/login', ret.data)
  router.replace('/admin')
}
</script>

<style lang="scss" scoped>

</style>

3. 在vite中自动导入模块文件

import { createStore, useStore } from 'vuex'

// 自动导入模块
// eager 同步,不能使用 promise
const moduleFiles = import.meta.glob('./modules/*', { eager: true })
let modules = {}
for (let key in moduleFiles) {
  let prop = /\.\/modules\/(\w+)\.js/.exec(key)[1]
  let value = moduleFiles[key].default
  modules[prop] = value
}

// 如果你现在用的是基于vue的服务器端渲染,此时一定要写成回调函数方案
const store = createStore({
  modules
})

export const useUserState = () => {
  let store = useStore()
  return store.state.user
}

export const useCommit = () => {
  let store = useStore()
  return store.commit
}

export const useDispatch = () => {
  let store = useStore()
  return store.dispatch
}

export default store

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/35221.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Silvaco example】GaN diode, Reverse-bias leakage current vs temperature

1、例子讲解 该示例演示了&#xff0c;GaN肖特基二极管中&#xff0c;因声子辅助隧穿&#xff08; phonon-assisted tunneling &#xff09;的反向偏置漏电流的温度依赖性建模。 例子参考以下论文&#xff1a; Pipinys P., and V. Lapeika, "Temperature dependence of …

Android入门第36天-以一个小动画说一下Android里的Handler的使用

简介 我们在前面的Android教程中已经提到过这么一件事&#xff1a;Android在启动后会有一个主线程。它不允许任何子线程去改变主UI线程里的内容。 这么做是为了妨止&#xff0c;万一有一个带有大事务的线程导致了渲染组件时间过长最终导致Android UI出现“闪退”、“崩溃”的…

突遇暴雨,怎样远程连接服务器

“我被封印在家里了&#xff0c;去不了单位&#xff0c;电脑关机了&#xff0c;用来远程开机远控&#xff0c;没想到遇到了大风暴雨&#xff0c;结果非常尴尬&#xff01;”最近收到好几个这样的粉丝留言。突遇暴雨&#xff0c;虽然准备了远程办公工具&#xff0c;但还没来得及…

引擎入门 | Unity UI简介–第1部分(10)

本期我们继续为大家进行Unity UI简介&#xff08;第一部分&#xff09;的后续教程 本篇内容 23.创建UI Manager 24.点击按钮时调用StartGame 文章末尾可免费获取教程源代码 本篇Unity UI简介&#xff08;第一部分&#xff09;篇幅较长&#xff0c;分为十篇&#xff0c;本篇…

vs调试技巧(详细)

调试技巧一.简介1.调试是什么2.调试的基本动作3.Debug和Rlease的介绍二.调试介绍1.调试环境准备2.快捷键的使用三.调试时看当前信息1.查看临时变量的值2.查看内存四.多多动手调试一.简介 1.调试是什么 调试本身是一个动作&#xff0c;是用来除去错误的动作 2.调试的基本动作 …

【前端】JavaScript-PC端网页特效

目录 一、元素偏移量offset系列 1.1offset概述 1.2offset与style区别 二、元素可视区client系列 立即执行函数 三、元素滚动scroll系列 三大系列总结 mouseenter和mouseover的区别 一、元素偏移量offset系列 1.1offset概述 offset系列相关属性可以动态的得到该元素的位置…

三十四、Java Iterator(迭代器)

Java Iterator&#xff08;迭代器&#xff09; Java Iterator&#xff08;迭代器&#xff09;不是一个集合&#xff0c;它是一种用于访问集合的方法&#xff0c;可用于迭代 ArrayList 和 HashSet 等集合。 Iterator 是 Java 迭代器最简单的实现&#xff0c;ListIterator 是 Co…

使用Emscripten编译Eigen算法模块为WebAssembly

前言 最近大降温&#xff0c;才意识到秋天是真的来了。古人有诗云&#xff1a;“眉如青山黛&#xff0c;眼似秋波横。”这足以说明秋天的水是多么的浪漫、多情、温柔。 秋天都懂得浪漫&#xff0c;你天天被人说木讷&#xff0c;何不做点改变&#xff1f;今天我来教大家属于程…

Android 开发音频录播中媒体录制器MediaRecorder和媒体播放器MediaPlayer的讲解及实战(超详细 附源码)

需要源码请点赞关注收藏后评论区留下QQ~~~ 一、媒体录制器MediaRecorder MediaRecorder是Android自带的音视频录制工具&#xff0c;它通过操纵摄像头和麦克风完成媒体录制&#xff0c;既可录制视频又可以单独录制音频 下面是它的常用方法 reset 重置录制资源 prepare 准备录制…

C/C++语言 3 —— 输入输出

C语言的io函数&#xff1a; printf 输出 和 scanf输入 是 C语言的标准IO函数的一部分&#xff1a; scanf函数会将屏幕上输入的字符&#xff0c;根据格式的要求转化为对应的数据&#xff1a; scanf 需要提供内存地址代码&#xff1a; #include <iostream> using nam…

【数字电路基础】进制转换:二进制、十进制、八进制、十六进制、反码、补码、原码

文章目录 一、无符号数进制转换1.1、十进制转二、八、十六1.1.1、 十进制转二进制1.1.2、 十进制转八进制1.1.2、 十进制转十六进制1.2、二、八、十六转十进制1.3 二进制转八、十六1.4 八、十六转二进制1.4 八转十六二、有符号数进制转换2.1 正数进制转换2.2 负数进制转换一、无…

Linux安装Tomcat详细教程(图文)

1、下载Linux版本****的Tomcat 下载地址 2、在usr目录下新建tomcat目录&#xff0c;然后将下载的tomcat拷贝到新建的tomcat目录中 创建目录命令&#xff1a;mkdir /usr/tomcat 3、进入到tomcat目录中解压下载的tomcat安装包 解压命令&#xff1a;tar -zxvf apache-tomcat-8…

自动驾驶感知算法实战13——自动驾驶感知未来发展方向分享

自动驾驶感知算法实战专栏:https://blog.csdn.net/charmve/category_12097938.html目录 发展方向:分享:自动驾驶3.0未来需要解决的问题发展方向: 多模态感知 多任务处理 大模型(通用智能) 分享: 自动驾驶3.0 第一,自动驾驶3.0是数据驱动,更是“真实场景下的海量大数据…

底物多肽Phe-Gly-His-Phe(NO2)-Phe-Ala-Phe-OMe、50572-79-7

胃蛋白酶的良好底物&#xff0c;也被组织蛋白酶 D 切割。 A good substrate for pepsin which is also cleaved by cathepsin D.编号: 402332 中文名称: Phe-Gly-His-Phe(NO2)-Phe-Ala-Phe-OMe CAS号: 50572-79-7 单字母: H2N-FGH-F(4NO2)-FAF-OMe 三字母: H2N-Phe-Gly-His-Phe…

企业信息化的供给侧改革

企业信息化建设供给侧改革的新思路 传统的企业信息化建设思路是什么呢&#xff1f;它是从需求侧的规划跟实施入手的&#xff0c;然后解决做哪些和怎么做业务信息化的问题&#xff0c;用不着关注承担这个项目建设的供给体系的质量、效率、结构问题。这就会导致在项目建设过程中…

[附源码]java毕业设计在线视频网站

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

垃圾分类解决方案-最新全套文件

垃圾分类解决方案-最新全套文件一、建设背景垃圾分类的意义1.为什么要进行垃圾分类2.智慧垃圾分类的重要性二、建设思路三、建设方案四、获取 - 垃圾分类全套最新解决方案合集一、建设背景 垃圾分类的意义 1.为什么要进行垃圾分类 将易腐有机成分为主的厨房垃圾单独分类&…

运动需要的装备有哪些?2022年运动装备推荐

全民开始运动的今天&#xff0c;越来越多的年轻人会选择在一天的忙碌之后通过简单的运动缓解疲劳。而在运动装备的选择上&#xff0c;由于种类和品牌太多&#xff0c;小白很难从中选择到适合自己的运动装备&#xff0c;作为一个资深运动爱好者&#xff0c;对这方面是非常在行的…

「运维有小邓」如何更有效的避免密码攻击

在这表文章中&#xff0c;让我们一起了解密码在网络安全中的重要性&#xff0c;在我们的日常工作中&#xff0c;密码泄露事件是常发生的&#xff0c; 那今天我们就一起了解ManageEngine ADSelfService Plus 是如何强化您的密码并加强您的企业AD域安全性的。 运维有小邓 2022 年…

MCE | 打破 Western Blot 玄学操作

看我一顿操作猛如虎&#xff1a; 电泳 → 转膜 → 封闭 → 孵一抗 → 孵二抗 → 检测&#xff0c;剩下的就是等待。 图 1. Western blot 操作流程简介[1] 我的实验结果中出现了各种稀奇古怪的玩意儿&#xff1f;&#xff1f;&#xff1f; ■ 古怪一&#xff1a;高背景 萌 Cece…