Pinia的理解
集中式状态管理
准备一个效果
加数字,变成字符串拼接,如何改变
方法一:v-model.number=“n”
<div class="count">
<h2>当前求和为:{{sum}}</h2>
<select name="" id="" v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="add">加</button>
<button @click="minus">减</button>
</div>
方法二:
<option :value="1">1</option>
<option :value="2">2</option>
<option :value="3">3</option>
LoveTalk.vue
准备一个数组,生成之后,再给他放进数组,这个之前没见过!
还有下面一个命名
Axios 是一个 基于 promise 的 HTTP 客户端,适用于 node.js
和浏览器。
<template>
<div class="talk">
<button @click="getLoveTalk">获取一句土味情话</button>
<ul>
<li v-for="talk in talklist" :key="talk.id">{{talk.title}}</li>
</ul>
</div>
</template>
<script setup lang="ts" name="LoveTalk">
import { reactive } from 'vue'
import axios from "axios";
import { nanoid } from 'nanoid'
//数据
let talklist = reactive([
{ id: 'ftrfasdf01', title: '今天天气好' },
{ id: 'ftrfasdf02', title: '今天天气好2' },
{ id: 'ftrfasdf03', title:'今天天气好3'}
])
//方法
async function getLoveTalk() {
//发请求
let result = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')
console.log(result);
console.log(result.data);
console.log(result.data.content);
//把请求回来的字符,包装成一个对象
let obj = {id:nanoid(),title:result.data.content} //简单写成title:content 上面let可以result改成 {data:{content}};还可以进一步 title {data:{content:title}}
//放到数组中
talklist.unshift(obj)
}
</script>
搭建pinia环境
安装pinia包
npm i pinia
main.ts
//引入pinia
import {ceratePinia} from 'pinia'
//创建pinia
const pinia = createPinia()
//安装pinia
app.use(pinia)
存储+读取数据
注意小点:
let obj = reactive({
a:1,
b:2,
c:ref(3)
})
let x = ref(9)
console.log(obj.a) //1
console.log(obj.b) //2
console.log(obj.c) //3,在reactive里面就可以直接不用.value
console.log(x) //ref实例对象
console.log(x.value) //9
存储数据 store/count.ts
import { defineStore } from 'pinia'
export const useCountStore = defineStore('count', {
//state真正存储数据的地方
state() {
return {
sum: 6
}
}
})
读取数据 Count.vue
<script setup lang="ts" name="Count">
import { ref } from 'vue';
import { useCountStore } from '@/store/count'
const countStore = useCountStore()
console.log('@@@', countStore);
//以下两种都可以拿到state中的数据
// console.log('@@@',countStore.sum);
console.log('@@@',countStore.$state.sum);
</script>
修改数据
第一种修改方式
<script setup lang="ts" name="Count">
//方法
function add() {
//第一种修改方式
countStore.sum += 1
}
</script>
第二种修改方式
<script setup lang="ts" name="Count">
//方法
function add() {
//第二种方式 数据很多的时候
countStore.$patch({
sum: 9,
school: '北京',
address:'朝阳'
})
}
</script>
第三种修改方式
Count.vue
<script setup lang="ts" name="Count">
//方法
function add() {
//第三种修改方式
countStore.increment(n.value)
}
</script>
store/count.ts
export const useCountStore = defineStore('count', {
actions: {
increment(value: number) {
console.log('increment被调用了', value)
//修改数据 this是当前的store
console.log(this.sum); //6
this.sum += 1
}
}
})
storeToRefs
将方法可以放到lovetalk.ts里面
export const useLoveTalkStore = defineStore('talk', {
actions: {
async getATalk() {
//发请求,下面这行写法是:连续解构+重命名
let { data: { content: title } } = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')
// //把请求回来的字符,包装成一个对象
let obj = { id: nanoid(), title } //简单写成title:content 上面let可以result改成 {data:{content}};还可以进一步 title {data:{content:title}}
// //放到数组中
this.talkList.unshift(obj)
}
}
})
在LoveTalk.vue里面可以直接调用
<script setup lang="ts" name="LoveTalk">
import { useLoveTalkStore } from '@/store/lovetalk';
const talkStore = useLoveTalkStore()
//方法
function getLoveTalk() {
talkStore.getATalk()
}
</script>
如何调用数据写法更简洁,使用storeTorefs
h3标题里面不用写countStore.sum、countStore.school 、countStore.address
<template>
<div class="count">
<h2>当前求和为:{{sum}}</h2>
<h3>欢迎来到:{{ school }},坐落于{{ address }}</h3>
<select name="" id="" v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="add">加</button>
<button @click="minus">减</button>
</div>
</template>
<script setup lang="ts" name="Count">
import { ref,toRefs } from 'vue';
import { useCountStore } from '@/store/count'
import { storeToRefs } from 'pinia';
const countStore = useCountStore()
//storeToRefs只会关注store中数据,不会对方法进行ref包裹
const {sum,school,address} = storeToRefs(countStore)
console.log('@@@', storeToRefs(countStore));
//数据
let n = ref(1) //用户选择的数字
function minus() {
countStore.sum -= n.value
}
</script>
<template>
<div class="talk">
<button @click="getLoveTalk">获取一句土味情话</button>
<ul>
//下面这行里面不用写talkStore.talkList
<li v-for="talk in talkList" :key="talk.id">{{talk.title}}</li>
</ul>
</div>
</template>
<script setup lang="ts" name="LoveTalk">
import { useLoveTalkStore } from '@/store/lovetalk';
import { storeToRefs } from 'pinia';
const {talkList} = storeToRefs(talkStore)
</script>
getters的使用
当state中的数据,需要经过处理后再使用时,可以使用getters配置
count.ts
export const useCountStore = defineStore('count', {
//state真正存储数据的地方
state() {
return {
sum: 6,
school: 'beijing',
address: 'chaoyang'
}
},
getters: {
// bigSum(state) {
// return state.sum * 10
// },
//第二种写法
bigSum: state => state.sum * 10,
upperSchool(state) {
return state.school.toUpperCase() //这里state改成this也可以
}
}
})
<template>
<div class="count">
<h2>当前求和为:{{sum}},放大十倍后{{ bigSum }}</h2>
<h3>欢迎来到:{{ school }},大写为:{{ upperSchool }},坐落于{{ address }}</h3>
<select name="" id="" v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="add">加</button>
<button @click="minus">减</button>
</div>
</template>
<script setup lang="ts" name="Count">
import { ref,toRefs } from 'vue';
import { useCountStore } from '@/store/count'
import { storeToRefs } from 'pinia';
const countStore = useCountStore()
//storeToRefs只会关注store中数据,不会对方法进行ref包裹
const {sum,school,address,bigSum,upperSchool} = storeToRefs(countStore)
//数据
let n = ref(1) //用户选择的数字
</script>
$subscribe的使用
通过store的$subscribe()方法侦听state及其变化
<script setup lang="ts" name="LoveTalk">
import { useLoveTalkStore } from '@/store/lovetalk';
import { storeToRefs } from 'pinia';
const talkStore = useLoveTalkStore()
const { talkList } = storeToRefs(talkStore)
talkStore.$subscribe((mutate,state) => {
console.log('talkStore里面保存的数据发生了变化',mutate,state);
localStorage.setItem('talkList',JSON.stringify(state.talkList))
})
//方法
function getLoveTalk() {
talkStore.getATalk()
}
</script>
lovetalk.ts 可以不是放一个固定数组,去上面本地存储的获取的数据,但如果一开始本地啥都没有,就是null,如果null重新获取unshift就无法取得数据,所以加一个或者||[]给一个空数组。注意:前面必须加JSON.parse不然无法解析
import { defineStore } from 'pinia'
import axios from 'axios'
import { nanoid } from 'nanoid'
export const useLoveTalkStore = defineStore('talk', {
actions: {
async getATalk() {
//发请求,下面这行写法是:连续解构+重命名
let { data: { content: title } } = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')
// //把请求回来的字符,包装成一个对象
let obj = { id: nanoid(), title } //简单写成title:content 上面let可以result改成 {data:{content}};还可以进一步 title {data:{content:title}}
// //放到数组中
this.talkList.unshift(obj)
}
},
//state真正存储数据的地方
state() {
return {
talkList: JSON.parse(localStorage.getItem('talkList') as string) || []
}
}
})