vue3组件常用的通信方式(父传子、子传父、pinia)
1.porps:实现父子组件通信,子组件接收的数据还是只读
父组件中,引入子组件并给子组件绑定一个money参数
<template>
<div id="app">
<h1>父组件</h1>
<h3>富一代资产{{ money }}元</h3>
<index1 :money="money"></index1>
</div>
</template>
<script lang="ts" setup>
import index1 from './view/index.vue'
import { ref } from 'vue'
let money = ref(1000000000000)
</script>
<style scoped>
#app {
width: 100vw;
height: 100vh;
color: #000;
padding: 50px;
box-sizing: border-box;
}
</style>
子组件中,使用defineProps接收,在template中,可以直接使用money,
<template>
<div class="index1">
<h1>子组件1</h1>
<h3>儿子不知道父亲有{{ porps.money }}元</h3>
<h3>
儿子知道了{{ money }}元
</h3>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const porps = defineProps(['money'])
console.log(porps)
</script>
<style lang="scss" scoped>
.index1 {
background-color: azure;
padding: 12px;
}
</style>
2.$emit
在vue框架中事件分为两种:一种是原生的DOM事件,另外一种自定义事件。原生DOM事件可以让用户与网页进行交互,比如click、dbdlick、change、mouseenter、mouseleave...自定义事件可以实现子组件给父组件传递数据。
父组件
<template>
<div id="app">
<h1>父组件</h1>
<h3>富一代资产{{ money }}元</h3>
<index1 :money="money" @xxx="handlerXXX"></index1>
<h3>{{ son }}</h3>
</div>
</template>
<script lang="ts" setup>
import index1 from './view/index.vue'
import { ref } from 'vue'
let money = ref(1000000000000)
let son = ref('')
const handlerXXX = (value: string) => {
son.value = value
}
</script>
<style scoped>
#app {
width: 100vw;
height: 100vh;
color: #000;
padding: 50px;
box-sizing: border-box;
}
</style>
子组件
<template>
<div class="index1">
<h1>子组件1</h1>
<h3>儿子不知道父亲有{{ porps.money }}元</h3>
<h3>
儿子知道了{{ money }}元
</h3>
<el-button @click="handlerClick">自定义事件</el-button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const porps = defineProps(['money'])
console.log(porps)
const $emit = defineEmits(['xxx'])
const handlerClick = () => {
console.log('触发事件')
$emit('xxx', '富二代上交9999元给富一代')
}
</script>
<style lang="scss" scoped>
.index1 {
background-color: azure;
padding: 12px;
}
</style>
3.pinia :集中管理状态容器,可以实现任意组件之间的通信
需先安装
npm install pinia
# 或者使用 yarn
yarn add pinia
新建store文件夹作为共享仓库 对仓库进行配置
// 创建仓库 index.ts
import { createPinia } from 'pinia'
// createPinia
let store =createPinia();
export default store
main.js : 引入 "./store"
import { createApp } from 'vue'
import App from "@/App.vue"
import "@/assets/style/common.scss"
import store from "./store"
const app = createApp(App)
app.use(store)
app.mount('#app')
定义仓库
import { defineStore } from "pinia";
import { ref, computed } from "vue"
let infoStore = defineStore("info", () => {
let num = ref(34233)
const updateNum = (value: number) => {
num.value = value
}
const newNum = computed(() => {
return num.value * 1000
})
return {
num,
newNum,
updateNum
}
})
export default infoStore
使用示例
<template>
<div class="index7">
<h1>子组件7</h1>
<h3>名字:{{ userInfo.name }}</h3>
<h3>{{ userInfo.totalMoney }}</h3>
<h4>组合式api:{{ info.num }}</h4>
<h4>组合式api使用计算属性:{{ info.newNum }}</h4>
<el-button @click="changeName">点击改名字</el-button>
<el-button @click="changeInfo">点击改num</el-button>
</div>
</template>
<script setup lang="ts">
import userStore from '@/store/modules/user'
import infoStore from '@/store/modules/info'
let userInfo = userStore()
const changeName = () => {
userInfo.updateName('库里南')
}
let info = infoStore()
console.log(info)
const changeInfo = () => {
info.updateNum(77777)
}
</script>
<style lang="scss" scoped>
.index7 {
background-color: rgb(115, 244, 175);
padding: 12px;
margin: 12px 0;
}
</style>