admin管理员组文章数量:1633926
文章目录
- 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
版权声明:本文标题:Vue3路由守卫、vuex的使用、vuex模块化拆分、vite中自动导入模块文件 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dongtai/1729177195a1188867.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论