首页 > 其他分享 >vue3中使用Pinia

vue3中使用Pinia

时间:2023-11-08 14:15:07浏览次数:33  
标签:const Pinia defineStore vue3 state pinia 使用 import store

Pinia 是一个用于 Vue 的状态管理库,类似 Vuex, 是 Vue 的另一种状态管理方案

三大核心:state(存储的值),getters(计算属性),actions也可支持同步(改变值的方法,支持同步和异步)

npm install pinia@next
or
yarn add pinia@next

模块化封装

创建实例

新建 store/index.ts(src目录下新建store文件夹,并创建index.ts文件)

创建 pinia 实例并导出所有模块

import { createPinia } from 'pinia'

const store = createPinia()

export default store
//main.ts
// 引入 pinia
import store from './stores'

const app = createApp(App)
app.use(store)

module

新建store/modules/urer.ts

modules 按模块定义对应的 store, user.ts 表示用户相关数据存储的仓库

// user.ts
import { defineStore } from 'pinia'

// 你可以对 `defineStore()` 的返回值进行任意命名,但最好使用 store 的名字,同时以 `use` 开头且以 `Store` 结尾。(比如 `useUserStore`,`useCartStore`,`useProductStore`)
// 第一个参数是你的应用中 Store 的唯一 ID。
export const useUserInfoStore = defineStore('useUserInfoStore', {
  // 其他配置...
  // state: 返回对象的函数
  state: () => {
    return {
      login: false
    }
  },
    getters: {
    newName: (state) => state.userInfo.name + 'vip',
  },
    actions: {
    //更新整个对象
    updateUserInfo(userInfo: { name: string; age: number }) {
      this.userInfo = userInfo;
    },
    //更新对象中某个属性
    updateAge(age: number) {
      this.userInfo.age = age;
    },
    //更新基础数据类型
    updateToken(token: string) {
      this.token = token;
    },
  },
})

constant

constant/index.ts 用来存放定义的一些全局常量信息,暂时不是很多,所以统一放在了一个文件下。

调用store

import { useUiSetStore } from '@/store/modules/uiSettings'
const ui = useUiSetStore()
ui.login = true

or

store 是一个用 reactive 包装的对象,直接解构读取state会失去响应式,因此需要storeToRefs,它将为每一个响应式属性创建引用;需通过 .value 读取解构出来的值

<template>
  <div>
    <div>姓名:{{ userInfo.name }} 年龄:{{ userInfo.age }}</div>
    <div>token:{{ token }}</div>
    <div>getter值:{{ newName }}</div>
    <button @click="handleUser">更新用户</button>
    <button @click="handleAge">更新年龄</button>
    <button @click="handleToken">更新token</button>
  </div>
</template>

<script setup lang="ts">
import { storeToRefs } from 'pinia';
import { useUserStore } from '@/store/user'; //路径别名,引入store

const userStore = useUserStore();

//storeToRefs 会跳过所有的 action 属性
const { userInfo, token, newName } = storeToRefs(userStore);

//action 属性直接解构
const { updateUserInfo, updateAge, updateToken } = userStore;

const handleUser = () => {
  updateUserInfo({ name: 'lisi', age: 24 });
};

const handleAge = () => {
  //userInfo是一个ref响应式引用,需通过.value取值
  updateAge(userInfo.value.age + 1);
};

const handleToken = () => {
  updateToken('23234');
};
</script>

Store

Store是一个保存状态和业务逻辑的实体,可以自由读取和写入,并通过导入后在 setup 中使用

// pinia.ts
import { defineStore } from 'pinia';

// defineStore 调用后返回一个函数,调用该函数获得 Store 实体
export const useStore = defineStore({
  // id: 必须的,在所有 Store 中唯一
  id: 'App',
  // state: 返回对象的函数
  state: () => ({
    count: 1
  })
});

访问state

默认情况下,您可以通过 store 实例访问状态来直接读取和写入状态:

const store = useStore();
store.counter++;

相互引用

每个store可看做一个hook。相互引用即调用不同hook

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

使用store的前提是保证pinia已被注册

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

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

重置状态

您可以通过调用 store 上的 $reset() 方法将状态 重置 到其初始值:

const store = useStore();
store.$reset();

改变状态

除了直接用 store.counter++ 修改 store,你还可以调用 $patch 方法。 它允许您使用部分“state”对象同时应用多个更改:

1.第一种

store.$patch({
  counter: store.counter + 1,
  name: 'Abalam'
});

2.第二种

const handleClick = () => {
  store.count++;
};

3.第三种方式 $patch 传递函数

const handleClickMethod = () => {
  // 这里的state就是指代的仓库中的state
  store.$patch((state) => {
    state.count++;
    state.helloWord = state.helloWord === "jspang" ? "Hello World" : "jspang";
  });
};

4.第四种方式 action

当业务逻辑很复杂的时候,就将方法写在store中的action

actions: {
    changeState() {
      this.count++
      this.helloWord = 'jspang'
    }
  }

解构使用

解构后可以直接省略掉 store,减少了代码量

import { mainStore } from "../store/counter";
import { storeToRefs } from "pinia";
const store = mainStore();
// 进行解构
const { helloWord, count } = storeToRefs(store);

解构必须要用到storeToRefs()函数!

替换state

您可以通过将其 $state 属性设置为新对象来替换 Store 的整个状态:

store.$state = { counter: 666, name: 'Paimon' };

您还可以通过更改 pinia 实例的 state 来替换应用程序的整个状态。 这在 SSR for hydration 期间使用。

pinia.state.value = {}

Getters

Getters 直接在 Store 上读取,形似 Store.xx,就和一般的属性读取一样,相当于 vue 中的计算方法

// 修改 store.js
import { defineStore } from "pinia";
import { otherState } from "@/store/otherState.js";

export const useStore = defineStore({
  id: "myGlobalState",
  state: ()=> ({
    count: 2
  }),
  getters: {
    // 一个基本的 Getter: 计算 count 的平方
    // 使用参数
    countPow2(state) {
      return state.count ** 2;
    },

    // 获取其它 Getter, 直接通过 this
    countPow2Getter() {
      return this.countPow2;
    }

    // 使用其它 Store
    otherStoreCount(state) {
      // 这里是其他的 Store,调用获取 Store,就和在 setup 中一样
      const otherStore = useOtherStore();
      return otherStore.count;
    },
  }
});

// otherState.js
import { defineStore } from "pinia";
export const useStore = defineStore({
  id: "otherState",
  state: ()=> ({
    count: 5
  }),
});

actions

Pinia 没有 Mutations,统一在 actions 中操作 state,通过 this.xx 访问相应状态
虽然可以直接操作 Store,但还是推荐在 actions 中操作,保证状态不被意外改变
action 和普通的函数一样
action 同样可以像 Getter 一样访问其他的 Store,同上方式使用其它 Store,这里不在赘述,详细请移步 官方文档 Actions

action

// store.js
export const useStore({
  state: ()=> ({
    count: 2,
    // ...
  })
  // ...
  actinos: {
    countPlusOne() {
      this.count++;
    },
    countPlus(num) {
      this.count += num;
    }
  }
})

可以自由扩展 官方文档 Plugins

异步 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 */
      }
    },
  },
});

数据持久化

由于pinia里没有自带的持久化存储,所以我们需要使用要持久化存储的插件 pinia-plugin-persistedstate npm地址:pinia-plugin-persistedstate 文档入口:pinia-plugin-persistedstate

npm i pinia-plugin-persistedstate
#或者使用 npm
yarn add pinia-plugin-persistedstate

基础使用

  1. 将插件添加到 pinia 实例上
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const store = createPinia()
store.use(piniaPluginPersistedstate) // 使用持久化插件
export default store
  1. 创建 Store 时,将 persist 选项设置为 true
// user.ts
import { defineStore } from 'pinia'

// 你可以对 `defineStore()` 的返回值进行任意命名,但最好使用 store 的名字,同时以 `use` 开头且以 `Store` 结尾。(比如 `useUserStore`,`useCartStore`,`useProductStore`)
// 第一个参数是你的应用中 Store 的唯一 ID。
export const useUserInfoStore = defineStore('userInfo', {
  // 其他配置...
  // state: 返回对象的函数
  state: () => {
    return {
      login: false
    }
  },
  persist: true // 开始数据持久化
})

配置

默认配置如下

修改默认配置

将一个对象传递给 Store 的 persist 属性来配置持久化。

import { defineStore } from 'pinia'

export const useStore = defineStore('main', {
  state: () => ({
    someState: '你好 pinia',
  }),
  persist: {
    // 在这里进行自定义配置
    key: 'my-custom-key', //将被持久化存储在 localStorage 中的 my-custom-key key 中
    storage: sessionStorage, //持久化存储在 sessionStorage中 ,默认localStorage
    paths: ['save.me', 'saveMeToo'], // 只有 save.me 和 saveMeToo 被持久化,而未设置的不会被持久化。
  },
})

问题点

  1. pinia 里存储的用户信息,刷新后数据恢复默认 , 使用持久化插件解决

  2. 在axios中使用 ,报错未挂载

    响应拦截器 中调用 uiSettings = useUiSetStore()

  3. 在 js 或vue hooks中单独使用报错

    错误

     "getActivePinia()" was called but there was no active Pinia. Did you forget to install pinia? 	const pinia = createPinia() 	app.use(pinia) This will fail in production..
    

    解决方式

    1. 为pinia单独新建一个文件store.js

    2. 然后在要使用pinia的js文件中导入

    import { createPinia } from 'pinia'
    import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
    const store = createPinia()
    store.use(piniaPluginPersistedstate)
    export default store
    

    使用

    import pinia from '@store/index'
    import { useUiSetStore } from '@/store/modules/uiSettings'
    const ui = useUiSetStore(pinia)
    

标签:const,Pinia,defineStore,vue3,state,pinia,使用,import,store
From: https://www.cnblogs.com/ouyangkai/p/17817241.html

相关文章

  • 使用云服务有哪些优势?
    云服务器帮助您快速构建更稳定、安全的应用,降低开发运维的难度和整体IT成本,使您能够更专注于核心业务的创新。那么云服务器相比VPS、独立服务器又有哪些优势呢?首先先了解一下什么是云服务器:1.什么是云服务器?云计算服务器(又称云服务器或云主机),是云计算服务体系中的一项主机产品......
  • WPF 使用 CommunityToolkit.Mvvm
    参考文档: IntroductiontotheMVVMToolkit-CommunityToolkitsfor.NET|MicrosoftLearn它是一个现代化,快速和模块化的MVVM库,对应用程序的结构或编译规范没有严格的限制。NuGet安装包搜索:CommunityToolkit.Mvvm导入usingCommunityToolkit.Mvvm;使用ObservableObjectpubli......
  • 使用Sysprep封装Windows
    前言:首先感谢前同事的经验教程分享,结合自己实际情况,再进行以下的归纳总结。封装过程不介入第三方工具,不做任何优化。序号任务1安装系统,软件2封装系统3捕获ISO,生成win文件4注入ISO5利用Ventoy制作U盘启动盘              ......
  • 记 grep命令在Ubuntu上使用失败的问题
    问题/任务我有一个任务,要用shell命令从文本文件中提取ip地址,文本文件内容就像这样:185.155.192.77--[17/Jul/2023:02:27:22+0000]"GET/HTTP/1.1"4041234我想到可以用grep来实现,找到一个ip地址的正则表达式,用来提取ip正好,命令行是这样:grep-E-o'\b(?:\d{1,3}.){3......
  • 无界鼠标的使用 (mouse without borders)
    下载:https://www.cnblogs.com/dengziqi/p/14613391.html官网https://www.microsoft.com/en-us/download/details.aspx?id=35460 使用:https://www.cnblogs.com/yufeng218/p/16264460.html ......
  • 防止DOS攻击(检测nignx日志若某个IP短时间的PV过大则使用防火墙将其禁掉)
    #!/bin/bashtime=`date|awk'{print$3"\\\\/"$2"\\\\/"$6}'`awk'$4~/'"${time}"'/{print$0}'access.log|awk'{ip[$1]++}END{for(iinip)printi,ip[i]}'|sort-rnk2|head>18.t......
  • C语言程序设计 随机函数的使用-随机点名做习题
    /*---------------------------------------随机点名做习题Author:emanleeDate:2008-04-24---------------------------------------*/#include"stdio.h"#include"conio.h"#include"time.h"voidmain(){intcount=4......
  • 【转】Lspatch使用
    原文地址:Lspatch使用原文作者:yuito写在前面通过使用模块,Android用户可以轻松地增加新功能、修改现有功能或增强应用程序的性能。但是,使用模块修改一般需要超级用户权限,也就是所谓的ROOT权限。这极大限度的限制了用户对于模块的使用。好在,Lsposed框架的开发队伍开发了一款名为......
  • 软件测试|Selenium Expected Conditions 模块使用
    简介在自动化测试中,页面元素可能需要一些时间才能加载或完成某种操作,为了确保测试的稳定性,我们需要等待特定条件变为真。Selenium提供了一个ExpectedConditions模块,用于智能等待页面元素的出现、可见、可点击等条件。本文将详细介绍如何使用Selenium的ExpectedConditions......
  • HarmonyOS NEXT调优工具Smart Perf Host高效使用指南
     在软件开发的过程中,很多开发者都经常会遇到一些性能问题,比如应用启动慢、点击滑动卡顿、应用后台被杀等,想要解决这些问题势必需要收集大量系统数据。而在收集数据的过程中,开发者则需要在各种工具和命令之间来回切换,不但容易错过问题发生时间点,数据收集完如何能将信息有效结合......