Vue3-Pinia学习
npm install pinia
import {createApp } from 'vue'
import './style.css'
import App from './App.vue'
import {
createPinia } from 'pinia'
const app = createApp(App)
app.use(createPinia())//pinia 装入到vue项目中
app.mount('#app')
javascript
state值设置
完成初始设置后,创建stores文件夹在这个文件夹下面创建一个用于数据共享的store.js文件。这些数据共享文件可以创建多个,并且针对每个不同的业务和功能都要设置一个数据共享文件。在stores文件夹下会保存多个Store 类 型的文件,这些文件名称最好根据所要执行的业务来命名,这样方便查找和维护。
首先,在store.js文件中导入pinia创建它的引用对象defineStore。你可以通过defineStore对象创建一个store数据共享器,这些数据共享器使用id来标识,代码通过id标识来找到要使用的数据共享器。我们现在创建一个有计数器功能的数据共享器,它的id名称是counter,返回引用的名称是useStoreCounter ,将这个引用设置成导出函数。
import {defineStore } from 'pinia';
export const useStoreCounter = defineStore('counter', {
state: () => ({
count: 1,
}),
});
现在定义好了一个计数Store,让我们在App.vue文件中看看是否可以访问和使用它了。导入store数据共享器获得到它的引用useStoreCounter对象,使用useStoreCounter创建一个Store对象counter,在模板中使用这个counter.count获得共享器中的保存的数字内容。
<script setup>
import {useStoreCounter } from './stores/store';
const counter = useStoreCounter();
</script>
<template>
<h1>Pinia 入门</h1>
<p>Count:{
{ counter.count }}</p>
</template>
html
在多个组件中同时使用共享数据
使用 Pinia 的目的是为了能够从所有组件都能访问 Store 中定义的数据,那我们来创建一些vue组件来检查它是否能访问到Store中的数据。在components文件夹下新建一个userPinia.vue文件,代码如下内容。
<script setup>
import { useStoreCounter } from '../stores/store';
const counter = useStoreCounter();
</script>
<template>
<h2>User中使用 Pinia</h2>
<p>共享数据:{
{ counter.count }}</p>
</template>
html
在 App.vue 文件中导入userPinia.vue组件,并在模板中使用这个组件。
<script setup>
import {useStoreCounter } from './stores/store';
import userPinia from './components/userPinia.vue';
const counter = useStoreCounter();
</script>
<template>
<h1>Pinia 入门</h1>
<p>Count:{
{ counter.count }}</p>
<userPinia />
</template>
html

actions动作设置
上面已经介绍在组件中如何使用和访问Store中的state值,那么我们怎么修改Store的state值中的数据呢?在Pinia的defineStore函数中提供了action属性,在这个action属性中可以添加内置方法,使用这些内置方法来修改defineStore中的state值数据。我们要在 store.js 文件里的defineStore 函数中添加一个增量累加函数sumNumber
import {defineStore } from 'pinia';
export const useStoreCounter = defineStore('counter', {
state: () => ({
count: 1,
user: {
name: 'zht',
dept: '部门一'
},
}),
//内置执行方法属性
actions: {
//累加方法
sumNumber() {
this.count++;
},
},
});
在App.vue文件中添加一个带有点击事件的按钮,设置点击事件执行Store对象Actions中定义的sumNumber函数
<script setup>
import {useStoreCounter } from './stores/store';
import userPinia from './components/userPinia.vue';
const counter = useStoreCounter();
</script>
<template>
<h1>Pinia 入门</h1>
<p>Count:{{ counter.count }}</p>
<div>
<h3>名称:{{counter.user.name}} </h3>
<button @click="counter.sumNumber">增加 +1</button>
</div>
<userPinia />
</template>
在浏览器中点击按钮,count中的数值会增加。这时候大家会发现父组件和子组件中的count值都会同时发生变化。这些数据共享器中的数据是具有反应特性的,更新反映在所有组件中。

我们来修改一下App.vue代码使用解构赋值方式来获得 Store 中的变量和函数引用。在template 标签不在使用 counter. 的方式来操作Store中变量与函数,这样使得代码变得更加简洁。
<script setup>
import {useStoreCounter } from './stores/store';
import userPinia from './components/userPinia.vue';
const {count,sumNumber,user } = useStoreCounter();
</script>
修改数据
direct
countstore.sum = 666;
patch Object
countstore.$patch({
sum:110,
school:'阿达'
})
patch Function
patch function:$patch(state => { state.sum = 10 })
方法修改
import { defineStore } from 'pinia'
export const useConuntStore = defineStore('count', {
actions:{
inrment(val:number){
this.sum +=val
}
},
//存储数据的地方
state() {
return {
sum:6,
school:'atguigu'
}
},
getters:{}
})
storeToRefs
- 借助
storeToRefs将store中的数据转为ref对象,方便在模板中使用 - 注意:
pinia提供的storeToRefs只会将数据做转换,而Vue的toRefs会转换store中数据(包含方法,方法不需要响应式)。
<template>
<div class="count">
<h2>当前求和为:{{sum}}</h2>
</div>
</template>
<script setup lang="ts" name="Count">
import { useCountStore } from '@/store/count'
/* 引入storeToRefs */
import { storeToRefs } from 'pinia'
/* 得到countStore */
const countStore = useCountStore()
/* 使用storeToRefs转换countStore,随后解构 */
const {sum} = storeToRefs(countStore)
</script>
getters
// 引入defineStore用于创建store
import {defineStore} from 'pinia'
// 定义并暴露一个store
export const useCountStore = defineStore('count',{
// 动作
actions:{
/************/
},
// 状态
state(){
return {
sum:1,
school:'atguigu'
}
},
// 计算
getters:{
bigSum:(state):number => state.sum *10,
upperSchool():string{
return this. school.toUpperCase()
}
}
})
组件里使用
const {increment,decrement} = countStore
let {sum,school,bigSum,upperSchool} = storeToRefs(countStore)
$subscribe
通过 store 的 $subscribe() 方法侦听 state 及其变化
import { useCountStore } from '@/store/count'
const talkStore = useTalkStore()
talkStore.$subscribe((mutate,state)=>{
console.log('LoveTalk',mutate,state)
localStorage.setItem('talkList',JSON.stringify(talkList.value))
})
回调参数:state
变化后的完整 state,直接拿到最新数据。
mutation(重点)
描述 “怎么改的”:
mutation.type // 'direct' / 'patch object' / 'patch function'
{解释
direct:直接赋值(countStore.sum = 10)
patch object:$patch({ sum: 10 })
patch function:$patch(state => { state.sum = 10 })
}
mutation.storeId // 当前 store 的 id(如 'count')
mutation.payload // $patch 传的对象(只有 patch object 才有)例如,{ state.sum = 10 }
store组合式写法
import {defineStore} from 'pinia'
import axios from 'axios'
import {nanoid} from 'nanoid'
import {reactive} from 'vue'
export const useTalkStore = defineStore('talk',()=>{
// talkList就是state
const talkList = reactive(
JSON.parse(localStorage.getItem('talkList') as string) || []
)
// getATalk函数相当于action
async function getATalk(){
// 发请求,下面这行的写法是:连续解构赋值+重命名
let {data:{content:title}} = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')
// 把请求回来的字符串,包装成一个对象
let obj = {id:nanoid(),title}
// 放到数组中
talkList.unshift(obj)
}
//getter
const bigSum = computed(() => sum.value * 10)
//必须return------------------------------------
return {talkList,getATalk,bigSum}
})
使用
<template>
<div class="talk">
<button @click="talkStore.getATalk">获取一句话</button>
<ul>
<li v-for="talk in talkList" :key="talk.id">{{ talk.title }}</li>
</ul>
</div>
</template>
<script setup>
import {useTalkStore} from '@/store/talk'
import { storeToRefs } from 'pinia';
const talkStore = useTalkStore()
const {talkList} = storeToRefs(talkStore)
talkStore.$subscribe((mutate,state)=>{
console.log('LoveTalk',mutate,state)
localStorage.setItem('talkList',JSON.stringify(talkList.value))
})
</script>
更多推荐

所有评论(0)