【精讲】pinia与vuex区别及pinia的使用
1,pinia和vuex的区别
pinia支持选项式api和组合式api 以及setup 语法糖
pinia没有mutations,只有state、getters、actions
pinia的模块化功能不提供modules,在Vuex中实现模块化操作时必须依赖于modules的良好兼容性
pinia体积小,性能较于vuex更好
2.1 Pinia 的安装
yarn add pinia |
|
|---|---|
# 或者使用 npm |
|
npm install pinia |
2.2 Pinia 的引入
Typically, in most projects, the common practice is to integrate components directly into main.js or main.ts files. In Vue 3, the approach involves using the $import construct to introduce components within the script section of an HTML file.
import { createApp } from 'vue' |
|
|---|---|
import App from './App.vue' |
|
import { createPinia } from 'pinia'; |
|
const app = createApp(App); |
|
const pinia = createPinia(); |
|
app.use(pinia); |
|
app.mount('#app') |
于项目的源码目录下设立一个存储目录专门用于管理Pinia组件。于该存储目录下可建立若干个JavaScript或TypeScript源代码文件分别对应不同的Pinia组件。例如,在存储目录下有一个示例index.js文件展示了基本组件的实现逻辑。
// 想要使用必须先引入 defineStore; |
|
|---|---|
import { defineStore } from 'pinia'; |
|
// 这里我们使用的是es6 的模块化规范进行导出的。 |
|
// defineStore 方法有两个参数,第一个参数是模块化名字(也就相当于身份证一样,不能重复 id) |
|
// 第二个参数是选项,对象里面有三个属性,相比于vuex 少了一个 mutations. |
|
export const useStore = defineStore('main', { |
|
state(){ // 存放的就是模块的变量 |
|
return { |
|
count: 10 |
|
} |
|
}, |
|
getters:{ // 相当于vue里面的计算属性,可以缓存数据 |
|
}, |
|
actions:{ // 可以通过actions 方法,改变 state 里面的值。 |
|
} |
|
}) |
2.4节 Pinia数据页面的操作指南 我们将基于Vue3框架设计一个演示文稿来介绍Pinia数据页面的操作流程。
<template> |
|
|---|---|
<div> |
|
<p>{{store.count}}</p> |
|
</div> |
|
</template> |
|
<script> |
|
// 这里引入我们导出的 useStore; |
|
import { useStore } from '../store/index.js' |
|
export default { |
|
setup(props) { |
|
// 值得注意的是 useStore 是一个方法,调用之后会给我们返回一个对象。 |
|
// 这个时候,你就会发现,页面上就能正常显示我们在index.js 里面的 state 里面定义的 count 数据。 |
|
const store = useStore(); |
|
return { |
|
store |
|
} |
|
} |
|
} |
|
</script> |
当然如果你对vuex辅助函数非常熟悉的话,你就会有疑问,在上述代码中的p标签中,不写store.count吗?直接写成count行合理吗?
很显然,在页面中我们仍然可以观察到 count 数据以页面形式呈现。具体来说,我们利用 pinia 提供的 storeToRefs 实现了这一功能。有心 notices 的小伙伴可能会注意到这一设计与我们在 Vue3 中使用的 toRefs 系统有着高度相似的特点。
3.pinia 中 修改 state 数据的方法。
3.1 直接修改 store 对象的数据
// html 代码 |
|
|---|---|
<p>{{count}}</p> |
|
<button @click="add">累计</button> |
|
// js 代码 |
|
const store = useStore(); |
|
const add = () => { |
|
store.count ++ |
|
} |
在运行上述代码时,我们观察到,在点击按钮进行累加操作时,页面中的计数发生变化。
3.1 $patch 方法传递一个对象来修改。
废话不多说,我们还是直接上代码。
// html 代码 |
|
|---|---|
<p>{{count}}</p> |
|
<button @click="add">累计</button> |
|
// js 代码 |
|
const store = useStore(); |
|
const add = () => { |
|
store.$patch({ |
|
count: store.count + 1 |
|
}) |
|
} |
借助以上代码我们同样能够实现数据的修改。可能会有疑问:为什么感觉比第一个方案显得更为复杂呢?给出的解释是 patch 同时支持修改多个数据。
// html 代码 |
|
|---|---|
<p>我是count数据{{count}}</p> |
|
<p>num{{num}}</p> |
|
<button @click="add">累计</button> |
|
// js 代码 |
|
const store = useStore(); |
|
const add = () => { |
|
store.$patch({ |
|
count: store.count + 1, |
|
num: store.num + 1 |
|
}) |
|
} |
通过上面的代码,你会发现,点击按钮,两个数据都会发生变化。
**3.3 patch方法接受一个函数用于执行修改操作** 之前我们介绍了通过patch方法传递一个对象来进行数据修改的方式。那么当传递的是一个函数时该如何进行操作呢?
// html 代码 |
|
|---|---|
<p>我是count数据{{count}}</p> |
|
<p>num{{num}}</p> |
|
<button @click="add">累计</button> |
|
// js 代码 |
|
const store = useStore(); |
|
const add = () => { |
|
store.$patch(state => { |
|
state.count++; |
|
state.num++; |
|
}) |
|
} |
|
// 特别注意:如果是传递函数的话 state 就是 我们在 pinia 模块里面定义的 存储 数据的对象,不在是页面中使用的 store 对象了。 |
通常情况下
// 首先我们需要在 actions 里面定义一个方法 |
|
|---|---|
import { defineStore } from 'pinia'; |
|
export const useStore = defineStore('main', { |
|
state(){ |
|
return { |
|
count: 10, |
|
num: 20 |
|
} |
|
}, |
|
getters:{ |
|
}, |
|
actions:{ |
|
piniaAdd(){ |
|
this.count++; |
|
// 特别注意:在这里this指向的就是当前的实例化出来的对象,piniaAdd 该函数如果换成箭头函数的话,this 指向就会发生 改变,不能再使用 this.count++; 了 |
|
} |
|
} |
|
}) |
|
// 页面 |
|
// html 代码 |
|
<p>我是count数据{{count}}</p> |
|
<p>num{{num}}</p> |
|
<button @click="add">累计</button> |
|
// js代码 |
|
const store = useStore(); |
|
const add = () => { |
|
store.piniaAdd(); |
|
} |
4.pinia 固化插件的使用
npm i pinia-plugin-persist --save --include=dev |
|
|---|---|
// 或者使用 yarn 安装 |
|
yarn add pinia-plugin-persist |
|
安装完成之后,我们可以在main.js 或者 main.ts 中引入。具体代码如下: |
|
import { createApp } from 'vue' |
|
import App from './App.vue' |
|
import { createPinia } from 'pinia'; |
|
// 下面是我们安装的固化插件。 |
|
import piniaPersist from 'pinia-plugin-persist' |
|
const app = createApp(App); |
|
const pinia = createPinia(); |
|
pinia.use(piniaPersist); |
|
// 特别注意:固化插件是 pinia.use 并不是 app.use |
|
app.use(pinia); |
|
app.mount('#app') |
|
具体模块中的使用看下面的代码: |
|
import { defineStore } from 'pinia'; |
|
export const useStore = defineStore('main', { |
|
state(){ |
|
return { |
|
count: 10, |
|
num: 20 |
|
} |
|
}, |
|
persist: { // 固化插件 |
|
enabled: true, // 开启存储 |
|
strategies: [ // 指定存储的位置以及存储的变量都有哪些,该属性可以不写, |
|
//在不写的情况下,默认存储到 sessionStorage 里面,默认存储 state 里面的所有数据。 |
|
{ storage: localStorage, paths: ["count"] }, |
|
// paths 是一个数组,如果写了 就会只存储 count 变量,当然也可以写多个。 |
|
] |
|
}, |
|
getters:{ |
|
}, |
|
actions:{ |
|
piniaAdd(){ |
|
this.count++; |
|
} |
|
} |
|
}) |
