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
// 使用 state
getContent(state) {
return state.name + state.content
},
方法二:使用this
// 使用this
getLive() {
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'
//使用别的state
showMessage(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: {
// 使用 state
getContent(state) {
return state.name + state.content
},
// 使用this
getLive() {
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
showMessage(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.list
console.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>
效果图