认识pinia
介绍pinia
介绍pinia
pinia是新一代的vue状态管理工具,具有如下特点
- 完整的 ts 的支持;
- 足够轻量,压缩后的体积只有1kb左右;
- 去除 mutations,只有 state,getters,actions;
- actions 支持同步和异步;
- 代码扁平化没有模块嵌套,只有 store 的概念,store 之间可以自由使用,每一个store都是独立的
- 无需手动添加 store,store 一旦创建便会自动添加;
- 支持Vue3 和 Vue2
安装pinia
yarn add pinia
npm install pinia
引入pinia
import { createApp } from 'vue'
import App from './App.vue'
import {createPinia} from 'pinia'
const store = createPinia()
let app = createApp(App)
app.use(store)
app.mount('#app')
初始化pinia
在src目录下新建store文件夹
新建文件 [name].js
定义store(仓库)
import { defineStore } from 'pinia'
第一个store文件
import { defineStore } from 'pinia'
//传入两个参数 第一个参数是id 可以在devtool中通过id来查看
//第二个是配置项 state 为数据 getter类似计算属性 action 修改数据的方法 支持同步异步
export const useUserStore = defineStore('user', {
state:()=>{
return {
num: 1
}
},
//类似于computed 可以帮我们去修饰我们的值
getters:{
},
//可以操作异步 和 同步提交state
actions:{
}
})
State
state 是允许直接修改值的 例如num++
<template>
<el-button @click="addFn">+1</el-button>
<div>{{ user.num }}</div>
</template>
<script setup>
import { useUserStore } from '_store/useUser.js'
const user = useUserStore()
const addFn = () => {
user.num++
}
</script>
<style scoped lang='less'>
</style>
批量修改store的值
<template>
<el-button @click="addFn">+1</el-button>
<div>num:{{ user.num }}</div>
<div>age:{{ user.age }}</div>
</template>
<script setup>
import { useUserStore } from '_store/useUser.js'
const user = useUserStore()
const addFn = () => {
user.$patch({
num: 100,
age: 300
})
}
</script>
<style scoped lang='less'>
</style>
批量修改函数形式
<template>
<el-button @click="addFn">+1</el-button>
<div>num:{{ user.num }}</div>
<div>age:{{ user.age }}</div>
</template>
<script setup>
import { useUserStore } from '_store/useUser.js'
const user = useUserStore()
const addFn = () => {
//推荐使用
user.$patch((state) => {
state.num++;
state.age = 40
})
}
</script>
<style scoped lang='less'>
</style>
通过原始对象修改整个实例
$state
您可以通过将store的属性设置为新对象来替换store的整个状态- 缺点就是必须修改整个对象的所有属性
<template>
<el-button @click="addFn">+1</el-button>
<div>num:{{ user.num }}</div>
<div>age:{{ user.age }}</div>
</template>
<script setup>
import { useUserStore } from '_store/useUser.js'
const user = useUserStore()
const addFn = () => {
user.$state = {
num: 10,
age: 30
}
}
</script>
<style scoped lang='less'>
</style>
通过actions修改
state.js
import { defineStore } from 'pinia'
//user为id是必传的
export const useUserStore = defineStore('user', {
state: () => {
return {
num: 1,
age: 18
}
},
getters: {},
actions: {
updataUser() {
this.num++
this.age = 10
}
}
})
<template>
<el-button @click="addFn">+1</el-button>
<div>num:{{ user.num }}</div>
<div>age:{{ user.age }}</div>
</template>
<script setup>
import { useUserStore } from '_store/useUser.js'
const user = useUserStore()
const addFn = () => {
user.updataUser()
}
</script>
<style scoped lang='less'>
</style>
解构state
-
在Pinia是不允许直接解构是会失去响应性的
-
修改 解构完之后的数据不会变,而源数据是会改变的
-
解决方案可以使用 storeToRefs
<template> <el-button @click="addFn">+1</el-button> <div>num:{{ num }}</div> <div>age:{{ age }}</div> </template> <script setup> import { storeToRefs } from 'pinia' import { useUserStore } from '_store/useUser.js' const user = useUserStore() const { num, age } = storeToRefs(user) console.log(num, age); const addFn = () => { user.num++ } </script> <style scoped lang='less'> </style>
action
同步 直接调用即可
import { defineStore } from 'pinia'
//user为id是必传的
export const useUserStore = defineStore('user', {
state: () => {
return {
num: 1,
age: 18
}
},
getters: {},
actions: {
updataUser() {
this.num++
this.age = 10
}
}
})
<template>
<el-button @click="addFn">+1</el-button>
<div>num:{{ num }}</div>
<div>age:{{ age }}</div>
</template>
<script setup>
import { storeToRefs } from 'pinia'
import { useUserStore } from '_store/useUser.js'
const user = useUserStore()
console.log(num, age);
const addFn = () => {
user.updataUser()
}
</script>
<style scoped lang='less'>
</style>
异步
import { defineStore } from 'pinia'
//user为id是必传的
const asyncFn = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve('info')
}, 3000)
})
}
export const useUserStore = defineStore('user', {
state: () => {
return {
num: 1,
age: 18,
info: ''
}
},
getters: {},
actions: {
async getInfo() {
const res = await asyncFn()
console.log(res)
this.info = res
}
}
})
<template>
<el-button @click="addFn">+1</el-button>
<div>num:{{ user.num }}</div>
<div>age:{{ user.age }}</div>
<div>info:{{ user.info }}</div>
</template>
<script setup>
import { useUserStore } from '_store/useUser.js'
const user = useUserStore()
const addFn = () => {
user.getInfo()
}
</script>
<style scoped lang='less'>
</style>
getter
-
1.使用箭头函数不能使用this this指向已经改变指向undefined 修改值请用state
getters: { sub: (state) => state.num + state.age }
-
2.普通函数形式可以使用this
sub() { return this.num + this.age }
-
3.getters 互相调用
```js
sub: (state) => state.num + state.age,
sub1() {
return this.num - this.age
},
number() {
return this.sub + this.sub1
}
```
持久化插件
-
下载插件pinia-plugin-persist
yarn add pinia-plugin-persist
-
store下的index.js
import { createPinia } from 'pinia' //pinia 持久化插件 import piniaPluginPersist from 'pinia-plugin-persist' const store = createPinia() store.use(piniaPluginPersist) export default store
-
在写的store.js文件下增加配置项 默认为sessionStorage
import { defineStore } from 'pinia' //user为id是必传的 const asyncFn = () => { return new Promise((resolve) => { setTimeout(() => { resolve('info') }, 3000) }) } export const useUserStore = defineStore('user', { state: () => { return { num: 1, age: 18, info: '' } }, getters: { sub: (state) => state.num + state.age, sub1() { return this.num - this.age }, number() { return this.sub + this.sub1 } }, persist: { enabled: true, strategies: [ { key: 'user', storage: localStorage, //可选session path: [] //可以选择保存的字段 其余的不保存 } ] } })