DC's blog DC's blog
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)

DC

愿我一生欢喜,不为世俗所及.
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)
  • html

  • css

  • javascript

  • jquery

  • UI库

  • 第一次学vue

  • 第二次学vue

    • vue语法基础
    • 创建vite项目
    • vue-router
    • pinia组件
      • pinia的基本使用
      • pinia登陆
    • cookie组件
    • axios组件
  • 前端
  • 第二次学vue
DC
2025-01-06
目录

pinia组件

状态管理组件, pinia 比vuex 更轻量级、更方便, pinia也是官方推荐的..

image-20250106183536980

# pinia的基本使用

  • pinia实现了 所有组件之间可以在内存方面共享数据

  • 我们可以把pinia想象成一个代理.. 该代理可以存储一系列的变量..(是存储在内存中的)

  • 所有的组件都从该代理中取变量, 修改变量.

  • 当某个组件修改了变量, 使用到该变量的所有组件都会自动同步修改后的变量的值..

  • 一旦刷新页面, pinia就会重新初始化, 数据全部回到初始值, 相当于没有修改过, 会造成数据的丢失..
    因而 pinia 绝对会与 本地存储(localStorage、cookie) 搭配食用. 以本地存储的持久化来解决刷新后数据丢失的问题.
    (详看后面小节的 登陆示例)

  • pinia由三个部分组成: state状态值、getter计算属性、action定义函数

state状态值 -- 就理解成 所有组件都可以取的全局变量 v1=123   v2={id:1,name:'wpq',token:'xxxx'}
getter计算属性 
  -- 可理解成 计算属性对原始的变量进行处理
     很多组件取到v2变量后,都要进一步取 v2.id v2.token -- 计算属性可以将这个重复的操作归纳到此处
action定义函数 -- 通常用于 取state中的数据进行业务逻辑处理 
1
2
3
4
5

65

菜单1修改了pinia中的变量,菜单2以及根组件App.vue中使用了该变量,会同步进行改变!
但注意,一旦刷新后,pinia中的数据就会回归初始值!!
-- 综上: 当前组件、当前组件的父组件、其他组件 中共享状态的数据!!
- 菜单1 > M1组件
- 菜单2 > M2组件
- 账户余额 > 根组件
1
2
3
4
5
6

关键代码如下:

image-20250107083549952


# pinia登陆

该示例是在 vue-router章节的 导航守卫小节 的登陆登出 的示例上 进行的补充修改..
先回顾下, 示例的需求和所用到的知识点..

现已经实现
1.登陆不含顶部,是单独的页面 - router路由嵌套结构 
2.登陆成功,跳转首页;退出登陆,跳转登陆页面 - 编程式导航/即js跳转 
3.未登录不能访问后台,应自动重定向登陆页面 - 路由守卫/即中间件

具体来说
1.> 登陆组件应是一级路由,后台组件也是一个一级路由,一系列菜单组件嵌套到后台组件中
2.> 登陆时,拿到表单数据,向后端发送请求进行验证,验证成功,获得json数据,里面包含用户信息以及token
    将其保存到本地缓存localStorage中,router.push跳转首页
  > 退出登陆时,清除本地缓存localStorage,router.push跳转登陆页
3.> 访问登录页面,该页面不需要登录就可以直接去查看;
    通过localStorage检查用户登录状态(登录成功,继续往后走next();未登录,重定向登录页面)

To do:接下来需实现
1.登陆成功后,退出登陆的按钮左侧应显示当前登陆用户的名字. -- pinia
2.待续: 补充,任何组件都可以取到pinia中的token登陆凭证,然后通过axios携带token向后端发送请求!!

思考一个问题:
Q: 是否可以仅用localstorage来实现接下来需实现的需求,而不用pinia.
A: - 对于不变的数据确实可以,但是当两个组件共用一个数据源(对象或数组)时.
     如果其中的一个组件改变了该数据源,希望另一个组件响应该变化时,pinia才是首选,loaclstorage是无法做到的.
   - 而且在pinia中,对于数据的修改可以先做一系列的验证! 有解藕的功效!!
   - pinia中的数据在内存里,loaclstorage的数据在本地文件里,从内存中读取的速度更快.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
image-20250107123249394

关键 新增和 改动的代码如下:

image-20250107130417241

新增 - src/stores/counter.js

import {ref, computed} from 'vue'
import {defineStore} from 'pinia'

export const userInfoStore = defineStore('userInfo', () => {
    // 基于localStorage
    // state部分
    // userString的值要么是null 要么是'{id: 1, name:"123e", token: "xxyakaxlod123d"}'
    const userString = ref(localStorage.getItem("info"))

    const userDict = computed(() => userString.value ? JSON.parse(userString.value) : null)

    const userId = computed(() => userDict.value ? userDict.value.id : null)
    const userName = computed(() => userDict.value ? userDict.value.name : null)
    const userToken = computed(() => userDict.value ? userDict.value.token : null)

    function doLogin(info) {
        // 基于localStorage
        localStorage.setItem("info", JSON.stringify(info));
        // ★★★ 注意:若不写这行代码,登陆成功后,压根跳转不过去
        // 因为程序一开始就读取了state部分的变量,页面不刷新的话,是不会重新读取state的!! 即刷新后,state中才会有值
        userString.value = JSON.stringify(info)  
    }

    function doLogout() {
        // 基于localStorage
        localStorage.clear()
        userString.value = null
    }

    // return啥,外部才能用啥,不使用的不给外部暴露,像userDict就没有暴露给外部.
    return {userId, userName, userToken, doLogin, doLogout}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

改动 - src/router/index.js

import {createRouter, createWebHistory} from 'vue-router'
import {userInfoStore} from "@/stores/counter.js";

const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),
    routes: [
        {
            path: '/login',
            name: 'login',
            component: () => import('../views/LoginView.vue'),
        },
        {
            path: '/',
            name: 'admin',
            component: () => import('../views/AdminView.vue'),
            children: [
                {
                    path: '',
                    name: 'home',
                    component: () => import('../views/HomeView.vue'),
                },
                {
                    path: '/about',
                    name: 'about',
                    component: () => import('../views/AboutView.vue'),
                },
            ]
        },
    ],
})


router.beforeEach((to, from, next) => {
    //1.白名单 eg:访问登录页面,该页面不需要登录就可以直接去查看
    if (to.name === "login" || to.name === "Index") {
        next()
        return
    }

    //2.检查用户登录状态(登录成功,继续往后走next(); 未登录,跳转到登录页面)
    /* 原先代码
    let username = localStorage.getItem("name")
    if (username) {
        next()
    } else{
        next({name: "login"})
    }
    */
    const store = userInfoStore()
    if (store.userId) {
        next()
    } else {
        next({name: "login"})
    }
})

export default router
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

改动 - src/views/LoginView.vue

<template>
    <div>
        <input type="text" placeholder="用户名" v-model="username">
        <input type="text" placeholder="密码" v-model="pwd">
        <input type="button" @click="doLogin" value="登陆">
    </div>
</template>

<script setup>
import {ref} from "vue";
import {useRouter} from "vue-router";
import {userInfoStore} from "@/stores/counter.js";

const router = useRouter()
const store = userInfoStore()

const username = ref("")
const pwd = ref("")

function doLogin() {
    // 1.获取数据 Todo-携带数据向后端发送请求进行验证
    /* 原先代码
    console.log(username.value, pwd.value)
    localStorage.setItem("name", username.value)
    */
    let info = {id: 1, name: username.value, token: "xxyakaxlod123d"}
    store.doLogin(info)
    // 3.跳转到首页
    router.push({name: "home"})
}
</script>

<style scoped></style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

改动 - src/views/AdminView.vue

<template>
    <RouterLink to="/">首页</RouterLink>
    |
    <RouterLink to="/about">关于</RouterLink>
    --
    {{ store.userName}}
    <span @click="doLogout" style="cursor: pointer;">退出</span>
    <RouterView/>
</template>

<script setup>
import {useRouter} from "vue-router";
import {userInfoStore} from "@/stores/counter.js";

let router = useRouter()
const store = userInfoStore()

function doLogout() {
    /* 原先代码
    localStorage.clear()
    */
    store.doLogout()
    // 跳转登陆页
    router.push({name: 'login'})
}
</script>

<style scoped></style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

补充, 为啥 pinia 中 本地缓存持久化时, 需要json序列化一下 localStorage.setItem("info", JSON.stringify(info));
不序列化, 就是一个对象集合.. 不好取值.

> info = {id:1,name:'wpq',token:'xxxxx'}
  {id: 1, name: 'wpq', token: 'xxxxx'}
> localStorage
  Storage {length: 0}
> localStorage.setItem('info',info)
  undefined
> localStorage.getItem('info')
  '[object Object]'    // 看这就明白了.
> localStorage.setItem('info',JSON.stringify(info))
  undefined
> v1 = localStorage.getItem('info')
  '{"id":1,"name":"wpq","token":"xxxxx"}'
> JSON.parse(v1)
  {id: 1, name: 'wpq', token: 'xxxxx'}
> JSON.parse(v1).id
  1
> JSON.parse(v1).token
  'xxxxx'

> localStorage.getItem('abcde')
  null
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

vue-router
cookie组件

← vue-router cookie组件→

最近更新
01
deepseek本地部署+知识库
02-17
02
实操-微信小程序
02-14
03
教学-cursor深度探讨
02-13
更多文章>
Theme by Vdoing | Copyright © 2023-2025 DC | One Piece
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式