什么时候使用pinia?
一个store应该包含可以在整个应用中访问的数据,这包括在许多地方使用的数据,如用户信息,以及需要通过页面保存的数据等
安装与使用
下载
npm install pinia
在main.js中引入
import { createPinia } from 'pinia'
const pinia = createPinia()
Vue.use(pinia)
使用pinia的小案例
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<main>
<h2>
{{ userInfoStore.age }}
</h2>
<h3>{{ userInfoStore.gettersUser }}</h3>
<button @click="userInfoStore.addAge">加1</button>
<h3>
{{ counter }}
</h3>
<h4>{{ gettersCounter }}</h4>
<button @click="addCounter">加1</button>
</main>
</div>
</template>
<script>
// @ is an alias to /src
import { useUserInfoStore, useCounterStore } from '@/stores/index.js'
import { storeToRefs } from 'pinia'
export default {
name: 'HomeView',
setup() {
const userInfoStore = useUserInfoStore()
const countStore = useCounterStore()
// const { counter, gettersCounter, addCounter } = useCounterStore // 直接解构,是不生效的,破坏了响应式
// 不能解构actions方法
const { counter, gettersCounter } = storeToRefs(countStore)
// actions里面的方法可以直接解构
const { addCounter } = countStore
console.log(userInfoStore)
console.log(countStore)
return {
userInfoStore,
countStore,
counter, gettersCounter, addCounter
}
}
}
</script>
修改state中的值
// 方式一:直接修改
countStore.counter++
// 方式二,批量修改$patch(对象)
countStore.$patch({
counter: 100,
name: '里斯',
arr: [...countStore.arr, 0]
})
// 方式三:批量修改,$patch(函数)强烈推荐
// state-->store中定义的state
countStore.$patch((state) => {
state.counter = 90
state.name = '赵丽颖'
state.arr.push(90)
})
// 方式四:逻辑比较复杂的时候,封装到actions里面
getters的使用
getters: {
// 相当于computed计算属性
gettersUser(state) {
return state.age + 5
},
// 不接收参数的时候
// 想使用this就不能用箭头函数
getterAge() {
// 可以直接通过this返回,这种方法,就不能对我们的返回值进行类型推导
return this.age + 1
},
// 访问其他的getters
getName(state) {
return this.getterAge + state.name
},
// 箭头函数使用方式
// 向getters传递参数,返回一个函数出去,没有了缓存的效果,和普通的函数一样
getNameJt: (state) => {
return (data) => state.name = data
},
// 访问其他的store
getterAgeOther(state) {
const counterStore = useCounterStore()
return state.age + counterStore.counter
}
},
actions的使用
actions: {
// 相当于methods
/**
* action中可通过this访问整个store实例,并支持完整的类型标注(以及自动补全),不同的是,action可以是异步的,
* 不能使用箭头函数,一定要使用普通函数
* 同样也可以使用其他模块的action,也可以使用async await
*/
addAge() {
this.age++
}
}
第一个参数位唯一ID
命名方式use+做什么的+store
export const useUserInfoStore = defineStore(唯一ID, {})
传参的第二个参数:类似于setup的方式创建
import { defineStore } from "pinia";
import { computed, ref } from "vue";
// 类似于 setup(){}
export const useCounterStore = defineStore('main', () => {
const counter = ref(130)
const name = ref('张三')
const arr = ref([1, 2, 3, 4])
const gettersCounter = computed(() => {
return counter.value + 5
})
function addCounter() {
counter.value++
}
// 将外面需要用到的值暴露出去
return {
counter, gettersCounter, addCounter, name, arr
}
})
传参的第二个参数:类似于options的方式创建
export const useUserInfoStore = defineStore('userInfo', {
// 类似与data,一定要return出去,防止数据污染(针对于服务端)
// 在定义的时候,state被定义为一个返回初始状态的函数,这使得pinia可以同时支持服务端和客户端
state: () => {
return {
name: '招募',
token: '',
role: '',
age: 20
}
},
getters: {
// 相当于computed计算属性
gettersUser(state) {
return state.age + 5
},
},
// vuex:actions(context,data){}
actions: {
// 相当于methods
/**
* action中可通过this访问整个store实例,并支持完整的类型标注(以及自动补全),不同的是,action可以是异步的,
* 不能使用箭头函数,一定要使用普通函数
* 同样也可以使用其他模块的action,也可以使用async await
*/
addAge() {
this.age++
}
}
})
对比vuex
搭配TypeScript一起使用时有非常可靠的类型推断支持
pinia没有mutations,而actions的使用不同,在actions中可以处理同步也可以处理异步,getters的使用是一致的
pinia没有总出口,全是模块化,需要定义模块名称,当多个模块需要协作的时候需要引入多个模块,vuex是有总入口的,在使用模块化的时候不需要引入多个模块
pinia在修改状态的时候不需要通过其他api,vuex需要通过commit,dispatch去修改。所以在语法上比vuex更容易理解和使用,灵活
pinia就是更好的vuex,建议在项目中可以直接使用它,尤其是使用了TypeAcript的项目