【Vue工程】006-Pinia

【Vue工程】006-Pinia

一、概述

1、官网

https://pinia.vuejs.org/zh/

2、官方 Demo

https://stackblitz.com/github/piniajs/example-vue-3-vite?file=README.md

3、简介

Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。

4、优点

  1. 使用 pinia作为数据仓库,可以很方便的在多个 组件/页面 中共用同一个变量;
  2. TypeScript 的支持更加友好;
  3. 可以在不重载页面的前提下修改仓库数据,且能实时响应在页面。

二、基本使用

1、安装

pnpm add pinia

2、创建 pinia 实例

创建 src/store/index.ts

import { createPinia } from 'pinia';

const store = createPinia();

export default store;

3、在 main.ts 注册

import { createApp } from 'vue';
import './style.css';
import App from './App.vue';
// 导入路由
import router from './router';
// 导入 store
import store from './store';

const app = createApp(App);
// 注册路由
app.use(router);
// 注册 store
app.use(store);
app.mount('#app');

4、创建 user.ts

创建 src/store/user.ts

import { defineStore } from 'pinia';

// 定义一个 userinfo 类型
export interface User {
  name?: string;
  age?: number;
  token?: string;
}

// defineStore 第一个参数是id,必需且值唯一
export const useUserStore = defineStore('user', {
  // state返回一个函数,防止作用域污染
  state: () => ({
    name: 'zibo',
    age: 26,
    token: '202305110056',
  }),
  // getters:获取 state 中的数据
  // getters 与 vue 中的 computed 类似,提供计算属性
  getters: {
    // 获取整个对象
    user: (state: User) => state,
    // 获取对象中某个属性
    newName: (state: User) => state.name + '123',
  },
  // actions:更新 state 中的数据
  actions: {
    // 更新整个对象
    setUser(user: User) {
      this.$patch(user);
    },
    // 更新对象中某个属性
    setName(name: string) {
      this.$patch({ name });
    },
  },
});

5、使用 useUserStore

<template>
  <div>姓名:{{ newName }} 年龄:{{ user.age }}</div>
  <div>token:{{ user.token }}</div>
  <button @click="handleUser">更新用户</button>
  <button @click="handleName">更新名字</button>
</template>

<script lang="ts" setup>
// 导入 useUserStore
import { useUserStore } from '@/store/user';
// 引入 storeToRefs 函数,使得解构 store 仍具有响应式特性
import { storeToRefs } from 'pinia';

// 通过 useUserStore 获取到 userStore
const userStore = useUserStore();

// storeToRefs 会跳过所有的 action 属性,只暴露 state 属性
const { user, newName } = storeToRefs(userStore);

// action 属性直接解构
const { setName, setUser } = userStore;

// 更新用户
const handleUser = () => {
  setUser({
    name: '张三',
    age: 18,
    token: '123456',
  });
};

// 更新名字
const handleName = () => {
  setName('李四');
};
</script>
<style scoped></style>

三、异步 actions

import { defineStore } from 'pinia';

const getData = () => {
  return new Promise<number>((resolve) => {
    setTimeout(() => {
      resolve(Math.random() * 100);
    }, 200);
  });
};

export const useListStore = defineStore('list', {
  state: () => {
    return {
      list: [] as number[],
    };
  },
  actions: {
    async updateList() {
      try {
        const data = await getData();
        this.list.push(data);
      } catch {
        /* empty */
      }
    },
  },
});

四、store 的相互引用

import { defineStore } from 'pinia';
import { useUserStore } from './user';

enum Sex {
  man = '男人',
  woman = '女人',
}

export const userSexStore = defineStore('user2', {
  state: () => {
    return {
      sex: Sex.man,
    };
  },
  actions: {
    updateSex() {
      const userStore = useUserStore();  // 引用其他store
      if (userStore.userInfo.name !== 'zhangsan') this.sex = Sex.woman;
    },
  },
});

五、路由钩子中使用 store

import { useUserStore } from '@/store/user';

router.beforeEach((to, from, next) => {
  // ✅ 这样做是可行的,因为路由器是在其被安装之后开始导航的,
  // 而此时 Pinia 也已经被安装。
  const store = useUserStore();
  if (!store.token) {
    next({
      path: '/login',
    });
  } else {
    next();
  }
});

六、数据持久化

1、安装插件

pnpm add pinia-plugin-persistedstate

2、使用插件

修改 src/store/index.ts

import { createPinia } from 'pinia';
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';

const store = createPinia();

store.use(piniaPluginPersistedstate); // 使用持久化插件

export default store;

3、在 store 模块中启用持久化

在 src/store/user.ts 中启用:添加 persist 配置项

当更新 state 值时,会默认存储到 localStorage 中

import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
  state: () => ({
    ...
  }),
  getters: { ... },
  actions: { ... },
    
  // 开始数据持久化
  persist: true,
})

4、修改 key 与存储位置

默认存储到 localStorage 的 key 值就是 store 模块 id 值。可以修改 key 值和存储位置

//将persist: true,改为
persist: {
  key: 'storekey', // 修改存储的键名,默认为当前 Store 的 id
  storage: window.sessionStorage, // 存储位置修改为 sessionStorage
},

5、自定义要持久化的字段

默认会将 store 中的所有字段都缓存,可以通过 paths 点符号路径数组指定要缓存的字段

persist: {
  paths: ['user.name'], // 存储 user 对象的 name 属性
},

七、补充:修改 state 的几种方法

1、直接修改

const add = () => store.counter ++

2、$patch 传递参数

const add = () => {
  store.$patch({
    count:store.counter + 2,
  })
};

3、$patch 传递方法

const add = () => {
 store.$patch(state => {
   state.counter += 10
 })
};

4、actons

  // actions:更新 state 中的数据
  actions: {
    // 更新整个对象
    setUser(user: User) {
      this.$patch(user);
    },
    // 更新对象中某个属性
    setName(name: string) {
      this.name = name;
    },
  },

八、user.ts setup 写法

import { defineStore } from 'pinia';
import { computed, reactive } from 'vue';

// 定义一个 userinfo 类型
export interface User {
  name?: string;
  age?: number;
  token?: string;
}

// defineStore 第一个参数是id,必需且值唯一
export const useUserStore = defineStore('user', () => {
  // 定义一个响应式对象
  const user = reactive<User>({
    name: 'zibo',
    age: 26,
    token: '202305110056',
  });
  // 计算属性:双倍年龄
  const doubleAge = computed(() => user.age! * 2);
  // 函数:更新整个对象
  const setUser = (newUser: User) => {
    user.age = newUser.age;
    user.name = newUser.name;
    user.token = newUser.token;
  };
  // 函数:更新对象中某个属性
  const setName = (name: string) => {
    user.name = name;
  };
  // 导出
  return {
    user,
    doubleAge,
    setUser,
    setName,
  };
});

九、在 Vue3 的 Setup 语法外使用 Pinia

如果你准备在 Vue3 的 Setup 语法外引入 Pinia 的 Store,例如 useCounterStore。

直接 import { useCounterStore } from "@/store/modules/xxxxxx" 是不行的,你得像这样:

import store from "@/store"

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  const doubleCount = computed(() => count.value * 2)
  function increment() {
    count.value++
  }

  return { count, doubleCount, increment }
})

/** 在 setup 外使用 */
export function useCounterStoreHook() {
  return useCounterStore(store)
}

然后引入 import { useCounterStoreHook } from "@/store/modules/xxxxxx" 即可!

vue-element-plus-admin是一个集成了Vue3全家桶和element-plus的后台管理系统。它使用了最新的Vue技术栈,包括Vue3、Vite、Vue-router 4、Pinia、element-plus和tailwindcss。这个项目的目的是为了方便开发者理解其他代码,并在开发自己的前端项目时进行参考。\[1\] 如果你想使用vue-element-plus-admin,你可以通过克隆项目的方式获取代码,使用命令`git clone https://github.com/mh185/vue3-elementPlus-admin.git`。然后进入项目目录,安装依赖项`npm install`。你可以使用`npm run dev`命令来运行项目,使用`npm run build`命令来构建项目。\[2\] 另外,还有一个类似的项目叫做element-plus-admin,它的地址是https://gitee.com/kailong110120130/vue-element-plus-admin。你可以将这个项目克隆下来,并将其整合到你的开发平台中。你可以将前端项目放在后端项目的根目录下,作为整个工程项目的一个模块。这样做的好处是在架构上实现了前后端的分离,但对于一个功能来说,前后端可以一起开发,从Git的提交和开发模式上都更加完整。\[3\] 总之,vue-element-plus-admin是一个使用Vue3和element-plus构建的后台管理系统,它提供了丰富的功能和组件,可以作为开发自己前端项目的参考。你可以通过克隆项目的方式获取代码,并根据需要进行安装和运行。 #### 引用[.reference_title] - *1* [element-plus-admin源码剖析](https://blog.csdn.net/weixin_30230009/article/details/124138774)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [vue3-elementPlus-admin](https://blog.csdn.net/weixin_50422141/article/details/124709356)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [vue-element-plus-admin整合后端实战——实现系统登录、缓存用户数据、实现动态路由](https://blog.csdn.net/seawaving/article/details/129766205)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值