类似 Vuex
1kb
左右,你甚至可能忘记它的存在!Vue官方
已决定将其作为新的推荐方案来代替 Vuex
。Pinia 官网:https://pinia.vuejs.org/zh/index.html
npm install pinia
// or
yarn add pinia
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
// 导入 pinia
import { createPinia } from 'pinia'
// 创建 pinia 实例
const pinia = createPinia()
// 挂载到根实例
const app = createApp(App)
app.use(pinia)
app.mount('#app')
在 src > store > index.js 中写入如下代码
import { defineStore } from "pinia"
// 1.定义并导出容易
// 参数1:容器的 ID,必须唯一,将来 Pinia 会把所有的容器挂载到跟容器
export const useMainStore = defineStore('main', {
/**
* 类似于组件的 data,用来存储全局状态
*/
state: () => {
return {
}
},
/**
* 类似组件的 computed,用来封装计算属性,有缓存功能
*/
getters: {
},
/**
* 类似组件的 methods,封装业务逻辑,修改 state
*/
actions: {},
})
state: () => {
return {
count:100
}
},
在 vue 文件中直接使用即可
<script setup lang="ts">
import { useMainStore } from './store'
const mainStore = useMainStore()
</script>
<template>
<div>
// 直接使用
<h1>{{ mainStore.count }}</h1>
</div>
</template>
state: () => {
return {
count: 100,
name:'张三'
}
},
需要引入 storeToRefs,将结构的数据转为响应式的数据
<script setup lang="ts">
import { useMainStore } from './store'
import { storeToRefs } from 'pinia'
const mainStore = useMainStore()
// 直接结构得到的并非响应式数据
// const { count , name} = mainStore
// 用 pinia 的 storeToRefs包裹后,结构出来就是响应式的数据
const { count , name} = storeToRefs(mainStore)
const handleChange = () => {
count.value+=20
}
</script>
<template>
<div>
<h1>{{ name }}</h1>
<h1>{{ count }}</h1>
<button @click="handleChange">+20</button>
</div>
</template>
注意点:
1、建议还是通过 $patch,批量更新对性能更友好
2、actions 中不能使用箭头函数定义,因为箭头函数本身并无 this
const handleChange = () => {
// 方式一:最简单的方式就是这样但不建议
mainStore.count++
// 方式二:批量更新方式: $patch 一个函数
mainStore.$patch(state=>{
state.count++,
state.name = 'jack'
})
}
先在 actions 中定义 (文件位置:/ src / store / index.ts)
actions: {
// 注意:此处定义不能使用箭头函数,因为箭头函数本身并无 this
changeState(){
// 相当于此时的 actions是 Vue模板中的 methos,state是 vue模板中的data
this.count += 2
this.name = '李四'
this.arr.push(10)
}
},
然后再 vue 文件的方法中调用即可
const handleChange = () => {
// 方式三:将逻辑复杂的封装到 actions 中处理
mainStore.changeState()
}
// 在 Vue 文件中调用时传入参数
const handleChange = () => {
// 传入参数10
mainStore.changeState(10)
}
// 在 actions 中接受参数并使用
actions: {
// 注意:此处定义不能使用箭头函数,因为箭头函数本身并无 this
changeState(step:number){
// 相当于此时的 actions是 Vue模板中的 methos,state是 vue模板中的data
this.count += step
}
},
gettes 中定义的方法有缓存,如果数据没变,多次调用也仅会执行一次
先在 getters 中定义
/**
* 类似组件的 computed,用来封装计算属性,有缓存功能
*/
getters: {
// 写法一:函数可以接收一个可选参数:state 状态对象
count20(state) {
console.log("调用了count20")
return state.count + 20
},
// 写法二:不用 state,则必须手动指定返回值的类型,否则类型推导不出来
count30() : number{
console.log("调用了count30")
return this.count + 30
},
// 写法三:接收 state 但是不用,麻瓜写法不建议
count40(state){
console.log("调用了count40")
return this.count + 40
}
},
Vue 文件中直接使用
<script setup lang="ts">
import { useMainStore } from './store'
const mainStore = useMainStore()
</script>
<template>
<div>
// 直接使用即可 -- 调用三次也仅会执行一次
<p>{{ mainStore.count20 }}</p>
<p>{{ mainStore.count20 }}</p>
<p>{{ mainStore.count20 }}</p>
</div>
</template>