pinia: 比vuex更适合vue3的状态管理工具,只保留了vuex 原有的 state, getters,actions 作用等同于 data computed methods,可以有多个 state
1.安装创建导入
安装:npm install pinia 或 yarn add pinia
创建stores/index.js
index.js
import { createPinia } from "pinia";
const pinia = createPinia()
export default pinia
导入
import { createApp } from 'vue'
import App from './App.vue'
import pinia from "./stores/index"
createApp(App).use(pinia).mount('#app')
2 使用state
在stores下新建 counter.js文件夹,使用defineStore 创建 传入一个(唯一名称), 命名时一般使用use + (唯一名称)
import { defineStore } from 'pinia'
const useCounter = defineStore('counter', {state: () => ({count: 99,name:'陆青',age:24,level: 200})
})
export default useCounter
在页面使用 不推荐使用解构赋值 ,解构之后不是响应式的 但可以通过vue 的 toRefs 以及 pinia 提供的 storeToRefs 变为响应式
<template><div><div>{{ counterStore.count }}</div><div>{{ count }}</div><button @click="add">+1</button><hr/><h1>{{name}}</h1><h1>{{age}}</h1><h1>{{level}}</h1><button @click="updateState">修改state</button><button @click="resetState">初始化state</button></div>
</template>
<script setup>
// pinia 只有 state getters actions 等同于 data computed methods
// pinia 可以有多个 state 使用defineStore 创建 传入一个(唯一名称), 命名时一般使用use + (唯一名称),
// pinia 不推荐使用解构赋值 ,解构之后不是响应式的 但可以通过vue 的 toRefs 以及 pinia 提供的 storeToRefs 变为响应式
import useCounter from "./stores/counter";
import { toRefs } from "vue";
import { storeToRefs } from "pinia";
const counterStore = useCounter();// const { count } = toRefs(counterStore);
const { count,name,age,level } = storeToRefs(counterStore);
function add() {counterStore.count++;
}
function updateState(){// 单个修改// counterStore.name = '陆景'// counterStore.age = 22//多个修改counterStore.$patch({name:'青子',age:100,level:220})
}
function resetState(){counterStore.$reset()
}
</script>
3使用 getters
在stores下新建 user.js文件夹
方法一:使用 state
// 使用 stategetContent(state) {return state.name + state.content},
方法二:使用this
// 使用thisgetLive() {return '我很喜欢的一句话是' + this.getContent},
接收函数
// 接收函数getFun(state) {return function (id) {for (var i = 0; i < state.list.length; i++) {const item = state.list[i]if(item.id == id){return item}}}},
使用别的state 里面的值
import useCounter from './counter'//使用别的stateshowMessage(state) {const storeCounter = useCounter()return this.getContent + '我是另一个state里面的' + storeCounter.name}
完整的user.js
import { defineStore } from 'pinia'
import useCounter from './counter'const useUser = defineStore('user', {state: () => ({list: [{name: 'vuex',id: 11},{name: 'pinia',id: 22}],name: '言念',content: '君子,温其如玉'}),getters: {// 使用 stategetContent(state) {return state.name + state.content},// 使用thisgetLive() {return '我很喜欢的一句话是' + this.getContent},// 接收函数getFun(state) {return function (id) {for (var i = 0; i < state.list.length; i++) {const item = state.list[i]if(item.id == id){return item}}}},//使用别的stateshowMessage(state) {const storeCounter = useCounter()return this.getContent + '我是另一个state里面的' + storeCounter.name}}
})
export default useUser
在页面使用
<template><div><h1>{{ storeUser.getContent }}</h1><h1>{{ storeUser.getLive }}</h1><h1>id为11:{{ storeUser.getFun(11)}}</h1><h1>{{ storeUser.showMessage }}</h1></div>
</template>
<script setup>
import useUser from "./stores/user";
const storeUser = useUser();
</script>
<style>
</style>
3 使用actions
在stores下新建 home.js文件夹
import { defineStore } from 'pinia'const useBanner = defineStore('banner', {state: () => ({banner: [],count: 10}),actions: {getCount(num) {this.count += num},async getBanner() {const res = await fetch('xxx/xxx/xxx')const data = await res.json()console.log(data.data.banner.list);this.banner = data.data.banner.listconsole.log(this.banner);}}
})export default useBanner
在页面使用
<template><div><h1>{{ storeBanner.count }}</h1><button @click="getAdd">+10</button><div v-for="(item,index) in storeBanner.banner" :key="index"><img :src="item.image"/></div></div>
</template>
<script setup>
import useBanner from "./stores/home";
const storeBanner = useBanner();
function getAdd() {storeBanner.getCount(10);
}
storeBanner.getBanner().then(res=>{console.log('请求完成了!!');
})
</script>
效果图