NoteZ_技术博客 NoteZ_技术博客
🏠 首页
  • 📚 Web技术
  • 📋 Npm笔记
  • 📑 Markdown
  • 📄 Git笔记
  • 📝 Nginx文档
  • 📓 Linux文档
  • 📖 技术文档
  • 📜 其他文档
  • 🧊 NodeJs
  • 🎡 Express
  • 🔥 Rust
  • 🎉 Koa2
  • 🍃 MongoDB
  • 🐬 MySql
  • 🥦 Oracle
  • 🍁 Python
  • 🍄 JavaScript
  • 🌰 CSS
  • 🧄 HTML
  • 🥑 Canvas
  • 🌽 Nuxt
  • 🍆 React
  • 🥜 Vue
  • 🧅 TypeScript
  • 🌶️ AI
  • 📘 分类
  • 📗 标签
  • 📙 归档
⚜️ 在线编辑 (opens new window)
  • 📁 站点收藏
  • 📦 前端组件库
  • 📊 数据可视化
  • 🌈 开源插件
  • 🎗️ 关于我
  • 🔗 友情链接
GitHub (opens new window)

NoteZ_技术博客

前端界的小学生
🏠 首页
  • 📚 Web技术
  • 📋 Npm笔记
  • 📑 Markdown
  • 📄 Git笔记
  • 📝 Nginx文档
  • 📓 Linux文档
  • 📖 技术文档
  • 📜 其他文档
  • 🧊 NodeJs
  • 🎡 Express
  • 🔥 Rust
  • 🎉 Koa2
  • 🍃 MongoDB
  • 🐬 MySql
  • 🥦 Oracle
  • 🍁 Python
  • 🍄 JavaScript
  • 🌰 CSS
  • 🧄 HTML
  • 🥑 Canvas
  • 🌽 Nuxt
  • 🍆 React
  • 🥜 Vue
  • 🧅 TypeScript
  • 🌶️ AI
  • 📘 分类
  • 📗 标签
  • 📙 归档
⚜️ 在线编辑 (opens new window)
  • 📁 站点收藏
  • 📦 前端组件库
  • 📊 数据可视化
  • 🌈 开源插件
  • 🎗️ 关于我
  • 🔗 友情链接
GitHub (opens new window)
  • JavaScript笔记

  • CSS笔记

  • HTML笔记

  • Canvas笔记

  • Nuxt笔记

  • React笔记

  • Vue笔记

    • markdown(md-editor-v3)简单使用
    • Prop 验证 与 非 Prop 的 Attribute
    • transition-group列表过渡
    • transition过渡&动画
    • vetur 中 eslint 的问题
    • vite 打包时内存溢出处理方案
    • Vite2 + Vue3添加svg的使用并通过svg实现自定义Icon组件
    • Vite项目构建优化之移除console.log和其他生产日志
    • vsCode 之 Monaco Editor 在 vue-cli3.0 中的使用方法
    • vue cli3 中的使用Luckysheet和Luckyexcel
    • vue 与 Koa 上传示例代码
    • vue 中 axios 如何取消请求,取消前面一个或多个请求
    • Vue 中 node-sass 安装失败简单解决方案
    • vue 中使用 pinia 状态管理教程
    • vue 中使用 web worker
    • vue 中封装 Axios 和 管理 API 接口
    • vue 中的 hash 与 history 两种路由模式
    • Vue 中的鼠标事件汇总
    • Vue 实现 Base64 图片上传
    • vue 强制刷新组件
    • Vue 组件中 v-mode 的本质以及实现方式
    • vue 组件中的.native 原生事件(@click.native)
    • Vue 组件中的.native原生事件(@click.native)
    • Vue 页面路由(router)权限控制和登陆验证
    • Vue 项目中如何在打包时清除 console 和 debugger
    • Vue 项目打包去除 .map 文件方法
    • Vue 预渲染之 prerender-spa-plugin 的配置使用
    • vue-cli 2.x和3.x配置移动端适配px自动转为rem
    • vue-cli3 如何实现pc端自适应
    • vue-cli3.0 开启 Gzip 压缩方法
    • Vue-cli3.0 监听路由变化的几种方式
    • Vue-cli3.0 结合 axios 解决生产环境中的跨域问题
    • vue-cli3.0移动端项目将px转换成rem
    • vue-cli3.x项目兼容ie解决方案
    • vue-router传递参数的几种方式
    • Vue2-ace-editor 基本使用方法
    • vue2.x 插槽slot使用总结
    • Vue2.x 组件通信方式
    • vue3 + vite 自适应(rem 适配)方法
    • vue3+vite:本地代理,配置proxy
    • Vue3.0 基础知识点总结
    • Vue3.0 挂载方法,添加全局属性
    • vue3.0之全局变量app.config.globalProperties的使用
    • vue3.2+elelmenui-plus+vite 按需导入ui组件库
    • vue3.x 中使用 ol (openlayer)地图
    • Vue3.x 组件通信方式
    • Vue3全局变量的定义和使用
    • Vuex使用记录
    • vue中使用html2canvas将html页面转为图片并且下载该图片
    • vue中父子组件之间的通信
    • Vue中的防抖函数封装和使用
    • Vue中配合clipboard.js实现点击按钮复制内容到剪切板
    • vue使用monaco editor时报错 Unexpected usage at EditorSimpleWorker.loadForeignModule
    • Vue列表渲染之数组、对象更新检测
    • Vue实现下拉滚动加载刷新功能
    • Vue开发中安装库经常报错
    • Vue技术框架
    • Vue生命周期
    • Vue监听store中数据变化的两种方式
    • Vue非父子组件之间通信的几种方式
    • Vue项目 解决 vuex 在页面刷新后数据丢失的问题
    • vue项目nginx部署子目录_vue 多项目部署_二级目录 copy
    • 使用 monaco-editor 汉化 右键菜单汉化
    • 使用 vite 脚手架创建 vue3 项目
    • 使用animate库
    • 使用vue实现鼠标框选文件的功能
    • 使用vue的transition标签结合css样式完成动画
    • 关于Vue项目优化方案总结
    • 关于解决vue-cli2.xx、vue-cli3.xx项目在ie中白屏的方案总结
    • 利用create-nuxt-app脚手架创建NuxtJS应用
    • 国际化插件 vue-i18n 使用方法
    • 在 vite-vue3.x 中的使用 vscode monaco-editor 方法
    • 在 Vue 中 如何使用 jsencrypt 实现 Rsa 进行加密
    • 在 vue 中使用 jsPlumb 总结
    • 在 vue 中使用 v-viewer 预览图方法
    • 在 Vue 中读取本地文本文件(兼容各种浏览器)
    • 在 vue 或 vuex 中如何使用 axios 进行请求操作
    • 在 vue 项目中 mock 的基本使用方法
    • 在 vue-cli3 项目更改 favicon 图标
    • 在 vue-cli3.0 中使用 Sass 全局变量
    • 在vue3+vite中使用markdown(v-md-editor)编辑器
    • 在vue中如何使用watch深度监听对象中值的变化
    • 基于 vue 列表拖拽排序
    • 基于 vue 图片裁剪(vue-cropper)
    • 基于 vue 的 CodeMirror 代码编辑器
    • 如何在 vue 中使用 swiper 插件创建轮播图
    • 如何在 vue 中实现代码高亮?
    • 如何在 Vue-cli3.0 中使用 prerender-spa-plugin 进行预渲染
    • 如何用 vue 实现一个虚拟列表
    • 清除项目中无用的console.log代码方法
    • 解决vue-cli3.0中提示syntax 'classProperties' isn't currently enabled的错误
    • 记录vite打包vue项目内存溢出问题及解决方法
    • Vite中使用 svg-sprite-loader加载svg文件
    • vite引入svg图片
    • vue 使用CompressionPlugin压缩解决打包后文件过大的问题
    • vue2.x递归组件 树形组件
    • vue3.x递归组件 树形组件
    • 使用Vite快速构建Vue3+ts+pinia脚手架
    • 启动vue项目时报错digital envelope routines__unsupported
    • Pinia 快速入门(使用教程)
      • Pinia 是什么?
      • pinia的优势
      • 安装pinia
      • 引入到项目
      • 创建store
        • 对象形式(Option Store)
        • 函数形式(Setup Store)
      • 组件内使用
        • 对象形式(Option Store)
        • 函数形式(Setup Store)
      • 仓库state
        • 读取state
        • 修改 state
        • 监听state
      • 仓库getters
        • 基本使用
        • 使用其他getter
        • 给getter传参
      • 仓库actions
      • 重置
      • 解构
      • 其他实例api
        • $subscribe
        • $onAction
      • 数据持久化
        • 安装插件
        • 将插件添加到pinia
        • 开启数据持久化
        • 其他操作
    • 关于 Vite Vue 辨别当前所处于什么(生产、开发)环境
  • TypeScript笔记

  • AI相关笔记

  • 开发文档
  • Vue笔记
NoteZ
2024-03-24
目录
Pinia 是什么?
pinia的优势
安装pinia
引入到项目
创建store
对象形式(Option Store)
函数形式(Setup Store)
组件内使用
对象形式(Option Store)
函数形式(Setup Store)
仓库state
读取state
修改 state
监听state
仓库getters
基本使用
使用其他getter
给getter传参
仓库actions
重置
解构
其他实例api
$subscribe
$onAction
数据持久化
安装插件
将插件添加到pinia
开启数据持久化
其他操作

Pinia 快速入门(使用教程)

# Pinia 是什么?

Pinia 是一个用于 Vue 的状态管理库,类似 Vuex, 是 Vue 的另一种状态管理方案,支持 Vue2 和 Vue3。

  • GitHub地址:https://github.com/vuejs/pinia (opens new window)
  • 官方文档:https://pinia.vuejs.org/ (opens new window)

# pinia的优势

  • vue2/3都可以用。
  • pinia中只有state、getter、action,抛弃了Vuex中的Mutation,用法更简单了。
  • pinia 中 action支持同步和异步
  • pinia 不用在使用模块(module)对store进行分割。
  • pinia 支持插件来扩展自身功能。
  • 支持服务端渲染 (SSR)

# 安装pinia

yarn add pinia
# 或者使用 npm
npm install pinia
1
2
3

# 引入到项目

安装完成后,就可以将pinia引入到项目中了,只需要调用createPinia()方法将pinia实例化,然后挂载到vue实例上就可以了。

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)

const pinia = createPinia()
app.use(pinia)

app.mount('#app')
1
2
3
4
5
6
7
8
9
10

# 创建store

下一步就应该去创建我们的数据仓库store了,store中存储的是我们需要共享的数据。

创建store需要调用pinia中的defineStore方法,该方法接受两个参数,第一个参数是store的唯一 id,第二个参数是store的配置属性。

defineStore方法配置store属性时,有两种写法,一种是Option 对象形式,一种是Setup 函数形式。

# 对象形式(Option Store)

与 Vue 的选项式 API 类似,我们需要传入一个带有 state、actions 与 getters 属性的 Option 对象。

与vue组件相比,你可以认为 state 是 store 的数据 (data),getters 是 store 的计算属性 (computed),而 actions 则是方法 (methods)。

这种方式非常直观,推荐使用。

// src/store/user.js
import { defineStore } from "pinia"

export const useUserStore = defineStore("user", {
    state: () => ({
        name: "石头",
        age: 18,
    }),
    getters: {
        getPerson: (state) => {
            return `${state.name}今年${state.age}岁了`
        }
    },
    actions: {
        changeName(name) {
            const that = this;
            setTimeout(() => {
                that.name = name;
            }, 1000)
        },
    },
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 函数形式(Setup Store)

与 Vue 的组合式 API 类似,你可以认为 state 是一个 ref,getters 是一个计算属性 (computed),而 actions 是一个方法 (methods)。

在 Setup Store 中:

  • ref() 就是 state 属性
  • computed() 就是 getters
  • function() 就是 actions

Setup store 比 Option Store 带来了更多的灵活性,因为你可以在一个 store 内创建侦听器,并自由地使用任何组合式函数。

注意

使用组合式函数会让 SSR 变得更加复杂。

import { defineStore } from "pinia"
import {computed, ref} from "vue";

export const useThemeStore = defineStore("theme", ()=>{
    const defaultSize = ref(16)

    const getBigSize = computed(() => {
        return  defaultSize.value + 10
    })

    const changeSize = (size) => {
        defaultSize.value = size
    }
    return {
        defaultSize,
        getBigSize,
        changeSize
    }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 组件内使用

引入上面创建的useUserStore,调用useUserStore方法得到仓库userStore实例。 可以直接使用userStore访问仓库中的属性。

# 对象形式(Option Store)

import { useUserStore } from "@/store/user"
const userStore = useUserStore()

console.log('user',userStore)

<template>
  <span>{{userStore.name}}</span>
  <span>{{userStore.age}}</span>
</template>
1
2
3
4
5
6
7
8
9

# 函数形式(Setup Store)

import { useThemeStore } from "@/store/theme"
const themeStore = useThemeStore()
console.log('theme',themeStore)
1
2
3

现在我们已经学会如何使用pinia了,但pinia中还有几个概念state、getter、action需要我们继续深入了解。

# 仓库state

state是仓库的原始数据,它是一个对象,你可以直接修改state的属性。

export const useUsersStore = defineStore("users", {
  state: () => {
    return {
      name: "小白菜",
      age: 25,
      sex: "男",
    };
  },
});
1
2
3
4
5
6
7
8
9

我们还需要知道state中的数据是如何读取和修改的,又有哪些需要注意的地方。

# 读取state

<script setup>
import { useUsersStore } from '@/stores/user'
const userStore = useUsersStore()
</script>
<template>
  <div>
   {{userStore.name}}
  </div>
</template>
1
2
3
4
5
6
7
8
9

# 修改 state

方式一:直接修改

userStore.name = 'xxx'
1

方式二:$patch({}) 对象形式 批量修改

$patch 是 pinia 提供的一个api,用来批量修改 state 中的数据,接收一个对象参数,对象中的属性就是 state 中的属性,值就是要修改的值。

可修改单个或多个属性,pinia内部做了优化,相同属性会被自动覆盖。

userStore.$patch({
 name: '土豆粉',
 age:19
})
1
2
3
4

方式三:$patch(fn) 函数形式 批量修改

这是$patch的另一种写法,回调默认接收一个参数,也就是store中的state,在回调函数中修改state中的数据。 推荐使用

userStore.$patch((state) => {
    state.name = '小白菜'
    state.age = 90
})
1
2
3
4

# 监听state

import { watch } from 'vue';
 
// 监听pinia中整个state
userStore.$subscribe((mutation, state) => {
  console.log(state);
})

// 监听pinia中整个state
watch(userStore.$state, (newValue, oldValue) => {
  console.log(newValue,oldValue);
})

// 只监听pinia中某一个值的变化
watch(() => userStore.count, (newValue, oldValue) => {
  console.log(newValue, oldValue);
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 仓库getters

getters 与Vue中的计算属性 computed 一样,就是仓库中的计算属性,它可以帮助我们快速获取仓库中的数据,并且可以对数据进行加工处理。

注意

  1. getters是一个对象
  2. 默认接收一个state参数,就是我们仓库中的state,该参数是可选的。
  3. 普通函数,可以使用 this 访问整个 Store 的实例

# 基本使用

export const useUserStore = defineStore('user', {
  state: () => ({
    name: '小白菜',
    age: 18,
  }),
  getters: {
      getUser() {
          return `${this.name},今年${this.age}岁`
      }, 
      getUser2: (state) => {
          return `${state.name},今年${state.age}岁`
      }
  },
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14

调用

import { useUserStore } from '@/stores/user'
const userStore = useUserStore()
console.log('getUser', userStore.getUser)
console.log('getUser2', userStore.getUser2)
1
2
3
4

# 使用其他getter

我们也可以在某个getter中使用其他的getter,这样就可以实现getter的复用了。

只需要将箭头函数转换为普通函数,函数内部通过 this 来调用当前 Store 上的数据和方法。

export const useStore = defineStore('main', {
  state: () => ({
    message: 'Hello World',
  }),
  getters: {
    fullMessage: (state) => `The message is "${state.message}".`,
    // 这个 getter 返回了另外一个 getter 的结果
    emojiMessage() {
      return `    ${this.fullMessage}`
    },
  },
})
1
2
3
4
5
6
7
8
9
10
11
12

# 给getter传参

我们还可以给getter传递参数,但getter 本身是不支持参数,需要返回一个带有入参的函数,实现给getter传参的效果。

注意

这样 Getter 将不再被缓存,只是个被调用的函数。

import { defineStore } from 'pinia'

export const useStore = defineStore('main', {
  state: () => ({
      message: 'Hello World',
  }),
  getters: {
    // 定义一个接收入参的函数作为返回值
    signedMessage: (state) => {
      return (newName) => `${newName} say: "The message is ${state.message}".`
    },
  },
})
1
2
3
4
5
6
7
8
9
10
11
12
13

调用

const store = useStore()

const signedMessage = store.signedMessage('Petter')

console.log('signedMessage', signedMessage)
// Petter say: "The message is Hello World".
1
2
3
4
5
6

# 仓库actions

actions属性就和我们组件代码中的methods相似,用来放置一些处理业务逻辑的方法。

actions属性值同样是一个对象,该对象里面也是存储的各种各样的方法,包括同步方法和异步方法。

这里不在赘述,详细请移步 官方文档Actions (opens new window)

import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
  state: () => {  
    return {
      name: 'hello',
    }
  },
  getters: {}, 
  actions: {    
    // 同步更新 name 值
    updateNameSync(newName) {
      this.name = newName
      return '同步修改state中的name值完成'
    },

    // 异步更新 name 值
    async updateName(newName) {
      return new Promise((resolve) => {
        setTimeout(() => {
          // 这里的 this 是当前的 Store 实例
          this.name = newName
          resolve('异步修改完成')
        }, 3000)
      })
    },
   },  
})
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

调用

在 Pinia 像普通的函数一样使用即可,不需要和 Vuex 一样执行 commit 或者 dispatch,

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

const store = useUserStore()

// 立即执行
store.updateMessageSync('同步')

// 3s 后执行
store.updateMessage('异步')
1
2
3
4
5
6
7
8
9

# 重置

那我们想重置state中的数据怎么办呢?

$reset()是pinia提供的一个api,用来重置state中的数据,将state中的数据重置为初始值。

// 通过调用 store 的 $reset() 方法将 state 重置为初始值。
userStore.$reset()
1
2

# 解构

store使用过程中,还有另外一个用法就是解构,我们可以把store中的state进行解构使用。

但是解构会失去响应式,需要 StoreToRefs 避免丢失响应式。

<script setup>
import { useUsersStore } from '@/stores/user'
const userStore = useUsersStore()
const {name} = userStore
</script>

<template>
 <div class="greetings">
  {{userStore.name}}
  {{name}}
 </div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12

State 也可以使用解构,但是解构会失去响应式,需要 StoreToRefs 避免丢失响应式

import { storeToRefs } from 'pinia'
const userStore = useUsersStore()
const { name } = storeToRefs(userStore)
1
2
3

# 其他实例api

上面已经介绍了$patch、$reset两个实例api,还有几个实例api不常用,我想我们应该了解一下。

# $subscribe

当state中的值任意一个发生变化的时候,就会触发该函数

/**
 * 当state中的值任意一个发生变化的时候,就会触发该函数
 * 
 * args: 里面会记录新旧值
 * state:就是当前操作的state的实例
 * options: 是一个对象,比如detached,这是一个boolean参数,当这个参数为true时,表明即使当前组件销毁后,也继续监控state里面值的变化,可选
 */
 goodsStore.$subscribe((args, state) => {
  console.log('args', args)
  console.log('state', state)
},{
  detached: true
})
1
2
3
4
5
6
7
8
9
10
11
12
13

# $onAction

当调用actions里面的函数的时候,就会触发该函数

/**
 * 当调用actions里面的函数的时候,就会触发改函数
 *
 * args:接收参数,里面封装了多个api:
 *      args.after:当$onAction里面的逻辑执行完成之后才会执行args.after函数逻辑,所以args.after放置的位置于执行顺序无关
 *      args.onError:当调用actions里面的函数发生错误时,args.onError函数也会执行
 *      args.args:接收调用actions里面的函数传递的参数,是一个数组
 *      args.name:执行的actions里面的函数的名称
 * detached: 这是一个boolean参数,当这个参数为true时,表明即使当前组件销毁时,也继续监控actions里面的函数调用,可选
 */
goodsStore.$onAction((args) => {
    args.after(() => console.log("args.after", "===="));
    console.log("args", args);
}, true);
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 数据持久化

store中的数据,刷新页面后就丢失了,如果想保留这些数据,就要用到数据持久化了。推荐使用 pinia-plugin-persistedstate (opens new window) 插件。

# 安装插件

yarn add pinia-plugin-persistedstate
# or
yarn add pinia-plugin-persistedstate
1
2
3

# 将插件添加到pinia

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

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
1
2
3
4
5

# 开启数据持久化

在仓库中指定persist为true,就可以开启数据持久化了。

开启后默认有以下配置:

  • 使用 localStorage 进行存储
  • store.$id 作为 storage 默认的 key
  • 使用 JSON.stringify/JSON.parse 进行序列化/反序列化
  • 整个 state 默认将被持久化

下面是Option Store写法,Setup Store 大同小异,去看官方文档吧。

import { defineStore } from 'pinia'

export const useStore = defineStore('main', {
  state: () => {
    return {
      someState: '你好 pinia',
    }
  },
  persist: true,
})
1
2
3
4
5
6
7
8
9
10

# 其他操作

除上面默认配置外,我们还可以进行一些其他的配置:

  • 指定存储的key
  • 指定要持久化的数据
  • 指定持久化的存储方式,默认 localStorage
import { defineStore } from 'pinia'

export const useStore = defineStore('store', {
 state: () => ({
  user: {
   name: '小白菜',
   age: 18,
  },
  company: '腾讯',
  department: '前端',
 }),
 persist: {
     // 指定持久化的key
     key: 'my-custom-key',
     // 指定要持久化的数据
     paths: ['user.name', 'company'],
    // 指定持久化的存储方式,默认 localStorage
     storage: sessionStorage,
 },
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

完结撒花 ,你又进步了一点点。

#vue#Pinia
上次更新: 2024/04/07, 16:22:38
启动vue项目时报错digital envelope routines__unsupported
关于 Vite Vue 辨别当前所处于什么(生产、开发)环境

← 启动vue项目时报错digital envelope routines__unsupported 关于 Vite Vue 辨别当前所处于什么(生产、开发)环境→

最近更新
01
Gitea数据备份与还原
03-10
02
Linux 中使用 rsync 同步文件目录教程
03-10
03
Linux 使用 rsync 互相传输同步文件的简单步骤
03-08
更多文章>
Theme by Vdoing | Copyright © 2019-2025 NoteZ,All rights reserved | 冀ICP备2021027292号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式