在第四篇中我们学习了
mixin
公共方法封装,VueRouter
的使用以及配置权限路由,本期我们将讲述Pinia
,并使用Pinia
和Axios
接口数据完成登录
功能以权限路由改造
本期需要掌握的知识如下:
Pinia
在项目中的使用及持久化
- 使用
Pinia
和Axios
完成登录
功能 - 使用
Pinia
完成对权限路由改造
1. Pinia 安装及使用
$ npm install pinia
安装pinia
$ npm i pinia-plugin-persist --save
安装pinia 持久化插件
main.js
引入 pinia
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'
// pinia 部分
import { createPinia } from 'pinia';
import piniaPersist from 'pinia-plugin-persist'
const pinia = createPinia()
pinia.use(piniaPersist)
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import 'nprogress/nprogress.css'
import axios from 'axios'
import VueAxios from 'vue-axios'
createApp(App).use(router).use(pinia).use(ElementPlus, { locale: zhCn }).use(VueAxios, axios).mount('#app')
scr
目录下新建 store
目录,并在该目录下新建 index.js
import { defineStore } from "pinia"
/**
* 这个 第一个参数main,也称为 id,是必要的,Pinia 使用它来将 store 连接到 devtools。
* 将返回的函数命名为use...(更好的语义化) 是跨可组合项的约定,以使其符合你的使用习惯。
*/
export const useStore = defineStore('user', {
state() {
return {
current_userInfo: {
id: '',
username: '',
password: '',
isOpen: '',
apiToken: ''
},
animationRoute: [],
}
},
/**
* 用来封装计算属性 有缓存功能 类似于computed
*/
getters: {
getNum(state) {
return `我是一个计数器${state.count}`
}
//或者不使用state传递参数直接使用this
//getNum(){
// return `我是一个计数器${this.count}`
// }
},
/**
* 编辑业务逻辑 类似于methods
*/
actions: {
SAVE_USER_MESSAGE(val) {
this.current_userInfo = val
},
SAVE_ANIMATION_ROUTER(val) {
this.animationRoute = val
}
},
persist: {
enabled: true, // 开启数据缓存
strategies: [
{
key: 'user',//存储key值
storage: localStorage, // 默认是sessionStorage
}
],
}
})
Pinia 解释说明:
state
相当于vuex
中的data
getters
等同于vuex
的getters
actions
相当于vuex
中的methods、actions
的和persist
持久化数据配置,防止 Pinia刷新后数据丢失
- Pinia 中是可以使用
this
关键字
2.登录功能实现
1.创建用户JSON文件和动态路由文件
·
// user.json
{
"data": [
{
"id": 1,
"username": "admin",
"password": "123456",
"isOpen": "true",
"apiToken": "token_assets"
}
]
}
// router.json
{
"data": [
{
"name": "admin",
"path": "/admin",
"hidden": false,
"meta": {
"title": "首页"
},
"children": [
{
"name": "admin/user",
"path": "user",
"hidden": false,
"meta": {
"title": "用户管理"
}
},
{
"name": "admin/role",
"path": "role",
"hidden": false,
"meta": {
"title": "角色管理"
}
}
]
}
],
"code": 200
}
2.创建 api 请求接口
// login.js
import request from '@/utils/request'
export const handleLogin = () => {
return request({
url: 'user.json',
method: 'GET'
})
}
// common.js
import request from '@/utils/request'
// 获取动态路由接口
export const animationRoute = () =>{
return request({
url:'router.json',
method:'GET'
})
}
3.页面搭建及接口请求
目录结构如下
index.vue
为父组件components
目录下的loginForm.vue
为子组件,包括Form
表单
这样做的原因是:
- 减少每个页面的代码,使代码更简洁、方便后期维护
- 复习
组件传值
index.vue
代码
<template>
<div class="login">
<loginForm @LoginEmit="LoginEmit" />
</div>
</template>
import { defineComponent, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
// 引入 pinia 方法
import { useStore } from '@/store/index.js'
// 引入 登录 api
import { handleLogin } from '@/api/login.js'
// 引入 权限路由 api
import { animationRoute } from '@/api/common.js'
// 引入 登录表单子组件
import loginForm from './components/loginForm.vue'
// 注册组件
const Component = defineComponent({
loginForm
})
/**
* @type data
* @description 所有数据都在此体现
* **/
const Router = useRouter()
const store = useStore()
/**
* @type methods
* @description 所有方法、事件都在此层中体现
* **/
// 登录按钮方法 由子组件触发并携带参数
const LoginEmit = async form => {
const { username, password } = form
let res = await handleLogin()
// 以下三行代码是判断登录账号密码是否正确
let currentUser = res.data.filter(item => { return item.username === username })
if (currentUser.length < 1) return ElMessage.error('用户不存在')
if (currentUser[0].password !== password) return ElMessage.error(