学习之前内容:Vue 3 快速上手学习笔记
第一步:pnpm install pinia
第二步:修改src/main.ts
import { createApp } from 'vue' import App from './App.vue' import {createPinia} from 'pinia' const app = createApp(App) const pinia = createPinia() app.use(pinia) app.mount('#app')
Store是一个保存状态、业务逻辑的实体,每个组件都可以读取、写入它。它有三个概念:state、getter、action,相当于组件中的: data、 computed 和 methods。
新建src/store/sum.ts
import { defineStore } from 'pinia' // 定义并暴露一个store export const useSumStore = defineStore('sum', { // 状态 state() { return { sum: 9, school: 'Hello', } }, // 计算 getters: {}, // 里面放方法,用于响应组件中的“动作” actions: { increment(value: number) { if (this.sum < 10) { this.sum += value // this就是当前的store } }, }, })
修改src\App.vue
新建src\components\Sum.vue
patch({ // sum: 666, // school: 'abc', // }) // 第三种修改方式 sumStore.increment(n.value) } function minus() { sumStore.sum -= n.value } .sum { background-color: skyblue; padding: 10px; border-radius: 10px; box-shadow: 0 0 10px; } select, button { margin: 0 5px; height: 25px; }
借助storeToRefs将store中的数据转为ref对象,方便在模板中使用。注意pinia提供的storeToRefs只会将数据做转换,而Vue的toRefs会转换store中所有数据(包括方法)。
修改src\components\Sum.vue
当state中的数据,需要经过处理后再使用时,可以使用getters配置。
修改getters配置src\store\sum.ts
getters: { bigSum: (state): number => state.sum * 10, upperSchool(): string { return this.school.toUpperCase() }, },
修改src\components\Sum.vue
通过store的$subscribe()方法侦听state及其变化。
修改src\components\Sum.vue
sumStore.$subscribe((mutate, state) => { console.log('sumStore', mutate, state) })
新建src\store\talkList.ts import { defineStore } from 'pinia' import axios from 'axios' import { nanoid } from 'nanoid' import { reactive } from 'vue'
export const useTalkStore = defineStore('talkList', () => { 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) // 放入数组中
}
return { talkList, getATalk } })
修改src\App.vue
新建src\components\TalkList.vue
.talk { background-color: orange; padding: 10px; border-radius: 10px; box-shadow: 0 0 10px; }
props是使用频率最高的一种通信方式,常用于父子通信:
修改src\App.vue
新建src\components\Father.vue .father { background-color: rgb(165, 164, 164); padding: 20px; border-radius: 10px; }
新建src\components\Child.vue
.child { background-color: skyblue; padding: 10px; box-shadow: 0 0 10px black; border-radius: 10px; }
常用于子传父,注意区分原生事件、自定义事件:
原生事件:
事件名是特定的(click、mosueenter等)
事件对象$event: 包含事件相关信息的对象(pageX、pageY、target、keyCode)
自定义事件:
事件名可以任意名称
事件对象$event: 是调用emit时所提供的数据,可以是任意类型
修改src\components\Father.vue
修改src\components\Child.vue
$event到底是啥?啥时候能.target:
与消息订阅与发布(pubsub)功能类似,实现任意组件间通信。
安装mitt:pnpm i mitt
新建src\utils\emitter.ts
import mitt from 'mitt' const emitter = mitt() // emitter.on() 绑定事件 // emitter.off() 解绑事件 // emitter.emit() 触发事件 // emitter.all.clear() 清理事件 export default emitter
在main.ts引入emitter
import { createApp } from 'vue' import App from './App.vue' import emitter from './utils/emitter' createApp(App).mount('#app')
src\App.vue
src\components\Father.vue
.father { background-color: rgb(165, 164, 164); padding: 20px; border-radius: 10px; } .father button { margin-left: 5px; }
提供数据组件src\components\Child1.vue,在合适时候触发事件。
.child1 { margin-top: 50px; background-color: skyblue; padding: 10px; box-shadow: 0 0 10px black; border-radius: 10px; } .child1 button { margin-right: 10px; }
接收数据组件src\components\Child2.vue:绑定事件、同时在卸载前解绑事件。
.child2 { margin-top: 50px; background-color: orange; padding: 10px; box-shadow: 0 0 10px black; border-radius: 10px; }
v-model用在HTML标签上:<input type="text" v-model="userName" />,本质上是:<input type="text" :value="userName" @input="userName = (<HTMLInputElement>$event.target).value" />。
v-model用在组件标签上,本质上是:
+ update事件。可以在组件标签上多次使用v-model:<AInput v-model:usr="userName" v-model:pwd="password" />。
用于实现当前组件的父组件,向当前组件的子组件通信,即祖传孙。
attrs会自动排除props中声明的属性(可认为声明过的props被子组件自己“消费”了)。
父组件src\components\Father.vue:
子组件src\components\Child.vue:
孙组件:
parent用于:子 → 父。
src\components\Father.vue
src\components\Child.vue
实现祖孙组件直接通信,具体使用:
src\components\Father.vue
src\components\Child.vue
src\components\GrandChild.vue
本文作者:a
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!