Pinia是什么?
官网解释:
Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。
从官网的解释不难看出,Pinia和Vuex的作用是一样的,它也充当的是一个存储数据的作用,存储在Pinia的数据允许我们在各个组件中使用。
实际上,Pinia就是Vuex的升级版,官网也说过,为了尊重原作者,所以取名Pinia,而没有取名Vuex,所以可以将Pinia比作为Vue3的Vuex。
Pinia的使用
1. 安装pinia
npm install pinia
2. 引入pinia
vue3 中引入的使用
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')
vue2 中引入的使用
import { createPinia } from 'pinia'
const pinia = createPinia()
new Vue({
el: '#app',
// 其他选项...
// ...
pinia,
})
3. Store
3.1 定义store
创建 store/user.js
import { defineStore } from 'pinia'
export const useStore = defineStore({
id: 'user',
state: () => ({
count: 0,
username: '10个肉包子'
}),
getters: {},
actions: {},
})
3.2 使用store
<script setup>
import storeUser from "@/store/user";
const { counter } = storeUser();
console.log(123, count);
</script>
4. State
4.1 定义state
export default defineStore('user', {
state: () => ({
count: 0,
username: '10个肉包子'
}),
});
4.2 使用state
- 方法 1. 直接获取
以 javascript 中的模块导出的方式导出 store 数据,state 中的数据均可通过变量.state 数据名获取
<script setup>
import storeUser from "@/store/user";
const { counter } = storeUser();
console.log(123, count);
</script>
- 方法 2. 解构获取
store 是一个 reactive 响应式对象,直接解构会使其失去响应式,类似 setup 中的 props,为了既可解构又可保持其响应式,可使用 storeToRefs,它将为每个 reactive 属性创建 refs
<script setup>
import { storeToRefs } from "pinia";
import storeUser from "@/store/user";
const { count } = storeToRefs(storeUser());
console.log(123, count);
</script>
<template>
<div>
{{ count }}
</div>
</template>
4.3 修改 state
- 直接修改 state:
<script setup>
import storeUser from "@/store/user";
const store = storeUser();
store.count++
console.log(123, store);
</script>
- $patch 已对象修改
<template>
<div>index-{{store.count}}</div>
</template>
<script setup>
import storeUser from "@/store/user";
const store = storeUser();
store.$patch({
count: 3,
});
</script>
缺点: 如果只需修改 state 数据中的某一项,仍然需要将整个对象传给 store。
或者
<template>
<div>index-{{store.count}}</div>
</template>
<script setup>
import storeUser from "@/store/user";
const store = storeUser();
store.$patch({
count: 3,
});
</script>
4.4 替换state
<template>
<div>index-{{store.count}}</div>
</template>
<script setup>
import storeUser from "@/store/user"
const store = storeUser()
store.$state = { count: 666, username: 'Paimon' }
</script>
4.5 重置state
一键回复默认的 state 数据
<template>
<div>index-{{store}}</div>
</template>
<script setup>
import storeUser from "@/store/user"
const store = storeUser()
store.$patch({
count: 3,
});
setTimeout(() => {
store.$reset()
}, 3000)
console.log(123, store)
</script>
5. Getters
5.1 获取数据
建议使用尖头函数
export const useStore = defineStore('user', {
state: () => ({
counter: 0,
}),
getters: {
doubleCount: (state) => state.counter * 2,
},
})
<template>
<div> {{ doubleCount }} </div>
<div> {{ counter }} </div>
</template>
<script setup>
import storeUser from "@/store/user"
import { storeToRefs } from 'pinia'
const store = storeUser();
const { doubleCount, counter } = storeToRefs(storeUser())
</script>
5.2 访问其他 getters
访问其他的 getter 需要使用 this, 注意:不能使用尖头函数了
export const useStore = defineStore('user', {
state: () => ({
counter: 0,
}),
getters: {
doubleCount(state) {
return state.counter * 2
},
doublePlusOne() {
return this.doubleCount + 1
},
},
})
5.3 getters 传递参数
export const useStore = defineStore('user', {
getters: {
getUserById: (state) => {
return (userId) => state.users.find((user) => user.id === userId)
},
},
})</pre>
<pre data-language="plain" id="tPS6e" class="ne-codeblock language-plain" style="border: 1px solid #e8e8e8; border-radius: 2px; background: #f9f9f9; padding: 16px; font-size: 13px; color: #595959"><template>
<p>User 2: {{ store.getUserById(2) }}</p>
</template>
<script setup>
import storeUser from "../../store/user";
const store = storeUser();
</script>
注意: getters are not cached anymore 即 getters 不会被缓存,只能函数调用。
5.4 访问其他的 getter
即想要哪个 getters 则调用哪个 getter,因为 pinia 没有总入口,和 vuex 有本质区别。
import { useOtherStore } from './other-store'
export const useStore = defineStore('main', {
state: () => ({
// ...
}),
getters: {
otherGetter(state) {
const otherStore = useOtherStore()
return state.localData + otherStore.data
},
},
})
5.5 使用 mapState 访问 store 中的数据
import { mapState } from 'pinia'
import storeUser from "@/store/user";
export default {
computed: {
...mapState(storeUser, ['doubleCount'])
...mapState(storeUser, {
myOwnName: 'doubleCounter',
double: state => state.doubleCount,
}),
},
}
6. Actions
6.1 获取方法
export const useStore = defineStore('user', {
state: () => ({
count: 0,
}),
actions: {
increment() {
this.count++
},
randomizeCounter() {
this.count = Math.round(100 * Math.random())
},
},
})
6.2 使用方法
- 同步的方式
<script setup>
import storeUser from "@/store/user"
const store = storeUser()
</script>
<template>
<button @click="store.increment()">增加</button>
</template>
- 异步的方式
import { mande } from 'mande'
const api = '@/api/users'
export const useUsers = defineStore('users', {
state: () => ({
userData: {},
}),
actions: {
async registerUser(login, password) {
try {
this.userData = await api.post({ login, password })
console.info(`Welcome back ${this.userData.name}!`)
} catch (error) {
console.error(error)
return error
}
},
},
})
Pinia 数据持久化插件
1. 安装
npm i pinia-plugin-persist
2. 引入
Vue2中引入使用
import Vue from 'vue'
import vueCompositionApi from '@vue/composition-api'
import { createPinia } from 'pinia'
import piniaPersist from 'pinia-plugin-persist'
import App from './App.vue'
const pinia = createPinia()
pinia.use(piniaPersist)
Vue.use(vueCompositionApi)
Vue.use(pinia)
new Vue({
pinia,
render: h => h(App),
}).$mount('#app')
Vue3中引入使用
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import piniaPersist from 'pinia-plugin-persist'
const pinia = createPinia()
pinia.use(piniaPersist)
createApp({})
.use(pinia)
.mount('#app')
pinia的优点
-
Vue2和Vue3都支持,这让我们同时使用Vue2和Vue3的小伙伴都能很快上手。
-
Pinia中只有state、getter、action,抛弃了Vuex中的Mutation,pinia直接抛弃它了,这无疑减少了我们工作量。
-
Pinia中action支持同步和异步,Vuex不支持
-
良好的Typescript支持,Vue3都推荐使用TS来编写,这个时候使用Pinia就非常合适了
- 无需再创建各个模块嵌套了,Vuex中如果数据过多,我们通常分模块来进行管理,稍显麻烦,而pinia中每个store都是独立的,互相不影响。 image
-
体积非常小,只有1KB左右。
-
pinia支持插件来扩展自身功能。
-
支持服务端渲染。
Pinia 与 Vuex对比
Pinia:State、Gettes、Actions(同步异步都支持)
Pinia图解:
image
Vuex:State、Gettes、Mutations(同步)、Actions(异步)
Vuex图解:
image
Pinia 当前最新版是 2.x,即支持 Vue2 也支持 Vue3;Vuex 当前最新版是 4.x,Vuex4 用于 Vue3,Vuex3 用于 Vue2。
网友评论