替代vuex的,可好用了
基本使用
写一个pinia
一种是这样用的,state返回的东西呢,在外部就可以直接用
//counter.js
import { defineStore } from 'pinia'
export const mainStore = defineStore('main',{
state:()=>{
return {
name: 'hello',
counter: 0
}
},
getters:{},
actions:{
}
})
另一种写法是
//counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const obj = reactive({
name:'tom'
})
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment ,obj }
})
这个return什么的,也是可以拿到的
调用他
//导入store
import {mainStore,useCounterStore} from "@/stores/counter";
//pinia
onMounted(()=>{
// 使用store
const store = mainStore()
console.log(store.name) //hello
// 使用store
const param = useCounterStore()
console.log(param.count) //0
param.increment() //让count++
console.log(param.count) //1
})
改变值
像常量一样地改变
和vuex一样,pinia存在的意义就是为了响应式地保存全局的值和改变值,但是pinia改变值可简单了
还是上面地例子,使用useCounterStore
import {useCounterStore} from "@/stores/counter";
//pinia
onMounted(()=>{
// 此时,param = {
// count = 0 ,
// doubleCount = 0 ,
// increment = () => { count.value++ }
// }
const param = useCounterStore()
console.log(param.count) // 0
//在这里,就进行了pinia的值的改变,很普通地改变,不写注释完全没有注意到是利用pinia进行全局调用了
//再也不用像vuex一样发action之类地这么麻烦
param.count ++
//此刻,在其他组件中打印,也是 1 !!
console.log(param.count) // 1
})
如果不想用单个对象接受,喜欢用const { a,b} = obj
这种方式,调用一个方法就可以
import {storeToRefs} from "pinia/dist/pinia";
onMounted(()=>{
// const store = mainStore()
// console.log(store.name)
//storeToRefs是pinia提供的
const { count } = storeToRefs(useCounterStore())
console.log(count.value) // 0
count.value ++
// param.count ++
console.log(count .value) // 1
})
传对象,改对象都是可以地
比如加多一个obj = {name:'tom''}
给useCounterStore
//counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const obj = reactive({
name:'tom'
})
return { count ,obj }
})
const store = useCounterStore()
console.log(store.obj.name) //tom
store.obj = {
age : 12
}
console.log(store.obj.age) //12 srore.obj.tom是不存在的了
$patch的改变方式
像上面的store.count ++
,也确实是可以胜任大多数工作了。
$patch是用于同时改变多个值的情况
比如一个按钮,点击事件,那就是
//点击事件
const changPinia = () => {
const store = useCounterStore()
// 多个值进行改变
store.$patch({
count: 1,
obj: {
name: 'jack'
}
})
console.log(store) //就是改变值之后的了
}
$patch((state) => {} 的方式
这个我也不知道和上面有什么区别,官方说的我也不懂额
反正可以这样用
const changPinia = async () => {
const store = useCounterStore()
store.$patch((state) => {
state.count = 1
state.obj.name = 'jack'
//这种是不行的
// state.obj = {
// name: 'jack'
// }
})
console.log(store)
}
在这里,传一个对象={}
就传不过去,不知道为什么
在store里面写函数进行调用
可以看到上面的例子,useCounterStore除了到处count,还有一个increment
函数,这个数可以让count++,直接调用,也是响应式的,其他组件拿到的值也会更新
onMounted(()=>{
const store = useCounterStore()
console.log(store.count) // 0
store.increment() // store.count ++
console.log(store.count) //1
})
直接调用store里面的函数,在setup写法是function就行,在选项式中要长这样,写在action里面
export const mainStore = defineStore('main',{
state:()=>{
return {
name: 'hello',
counter: 0
}
},
getters:{},
actions:{
change(){
this.counter = 1
}
}
})
选项式和组合式pinia的转换
一开始的2个例子,一个就是用选项式的,一个就是组合式的,目前尤雨溪推荐组合式的
export const mainStore = defineStore('main',{
state:()=>{
return {
name: 'hello',
counter: 0
}
},
getters:{
counterShow(state){
return state.counter + 2;
}
},
actions:{
change(){
this.counter = 1
}
}
})
转换成组合式就是
export const mainStore = defineStore('main', () => {
//state
const name = ref('hello')
const counter = ref(0)
// getters
const counterShow = computed(() => {
return counter.value + 2
})
//action
const change = () => {
counter.value++
}
return {name, counter, counterShow, change}
})
调用的方法都是一样的
全局注册避免重复打包
可以看到,pinia的使用流程是这样的
但是如果user store在每个组件都用到,每个组件都要将store打包一次,就会越来越大了
所以我们最好用一个全局注册的总入口,组件调用先调用总入口,再从总入口调用对应的store
但是!我不知道怎么做,没实践过,给后日留坑了
注意的点
1)注意的是,pinia要使用的时候,最好都是在内部生成一个store的,不要在外面生成,比如
setup
//不好
const store = mainStore()
onMounter(()=>{
//好
const store = mainStore()
})
2)番外:useStorage的使用
useSessionStorage('sid',"asd")
//等价于
sessionStorage.setItem("sid","asd")
useSessionStorage('sid',null)
//等价于
sessionStorage.getItem("sid")
3)如果和localStorage或者useSessionStorage绑定了,也会自动改变
比如一开始就定义了 const sid = ref(useSessionStorage('sid',null))
那么在用pinia的时候改变了sid的值,不用手动改他会直接将sessionStorage中的值也一起修改的
建议就是,基础类型传空,对象类型需要设置一下
//相当于获取值
const sid = ref(useSessionStorage('sid', null))
//相当于获取值,要加配置{}则不传,不然会默认传个{}的
const userInfo = reactive(useSessionStorage('userInfo', {},{writeDefaults:false}))
4)在store里面写watch也是能够观察到的
5)bug?
有个很奇怪的点,当pinia和useStorage绑定的时候,如果我想直接通过useStorage访问存储,会返回一个proxy或者refImpl,而且转格式也转不回来。
就只能通过pinia来读取了