vue3组件的通信方式

文章介绍了Vue中组件间的通信方式,如props、emit、ref以及状态管理工具pinia的使用。还讨论了v-model的特性,以及provide/inject用于父子组件数据传递的方法。最后提到了mitt.js作为事件总线在跨组件通信中的应用。
部署运行你感兴趣的模型镜像

1 props

父组件

<template>
    <div class="home">
        <child :list="list"></child>
        <div>
            <input v-model="value" type="text" placeholder="输入"/>
            <button @click="handleAdd" type="button">添加</button>
        </div>
    </div>
</template>
 
<script setup lang="ts">
    import child from "./homr/index.vue"
    import { ref} from "vue";
    const list = ref (['JavaScript', 'HTML', 'CSS'])
    const msg=ref('父组件的值');
    const handleAdd = () =>{
        list.value.push(msg.value)
    }
</script>
子组件接收父组件的值进行渲染

<template>
        <div >
            <div v-for="a in props.list" :key="a">{{ a }}</div>
        </div>
</template>
    
<script setup lang='ts'>
    import { defineProps} from 'vue'
    const props =defineProps({
        list:{
            type :Array,
            default :()=>[]
        }
    })
</script>
二,子组件传值 父组件接受
1 emit 

子组件

<template>
        <div>
            <input v-model="value" type="text" placeholder="输入"/>
            <button @click="handleSubmit" type="button">添加</button>
        </div>
</template>
    
<script setup lang='ts'>
    import {ref, defineEmits} from 'vue'
    const a=ref('1')
    const emits=defineEmits(['add'])
    const handleSubmit=()=>{
        emits('add',a.value)
        a.value=''
    } 
</script>
父组件 只需要监听子组件自定义的事件 

<template>
    <div>
        <div v-for="a in list" :key="a">{{ a }}</div>
        <indexMy @add="handleAdd"></indexMy>
    </div>
</template>
<script setup lang="ts">
    import {ref} from "vue"
    import indexMy from './my/My.vue'
    const list = ref(['JavaScript','HTML','CSS'])
    const handleAdd=value =>{
        list.value.push(value)
    }
</script>
三,v-model
v-model是vue 中出色的语法糖

<component v-model:title="page"></component>
子组件

<template>
        <div>
            <input v-model="value" type="text" placeholder="输入"/>
            <button @click="handleAdd" type="button">添加</button>
        </div>
</template>
    
<script setup lang='ts'>
    import {ref, defineEmits ,defineProps} from 'vue'
    const value=ref('')
    const props = defineProps({
        list:{
            type :Array,
            default :()=>[]
        }
    })
    const emits=defineEmits(['update:list'])
    const handleAdd=()=>{
        const arr=props.list
        arr.push(value.value)
        emits('update:list',arr)
        value.value=''
    } 
</script>
在子组件中我们首先定义props和emits,然后添加完成之后emit指定事件。

注:update:*是Vue中的固定写法,*表示props中的某个属性名。

<template>
    <div>
        <div v-for="a in list" :key="a">{{ a }}</div>
        <indexMy v-model:list="list"></indexMy>
    </div>
</template>
<script setup lang="ts">
    import {ref} from "vue"
    import indexMy from './my/My.vue'
    const list = ref(['JavaScript','HTML','CSS'])
</script>
四,refs
在使用选项式API时,我们可以通过this.$refs.name的方式获取指定元素或者组件,但是组合式API中就无法使用哪种方式获取。如果我们想要通过ref的方式获取组件或者元素,需要定义一个同名的Ref对象,在组件挂载后就可以访问了。

<template>
    <div>
        <div v-for="a in childRefs?.list" :key="a">{{ a }}</div>
        <indexMy ref="childRefs"></indexMy>
    </div>
</template>
<script setup lang="ts">
    import {ref} from "vue"
    import indexMy from './my/My.vue'
    const childRefs  = ref(null)
</script>
子组件

setup组件默认是关闭的,也即通过模板ref获取到的组件的公开实例,不会暴露任何在**

<template>
        <div>
            <input v-model="value" type="text" placeholder="输入"/>
            <button @click="handleAdd" type="button">添加</button>
        </div>
</template>
    
<script setup lang='ts'>
    import {ref, defineExpose} from 'vue'
    const list=ref(['JavaScript', 'HTML', 'CSS'])
    const a=ref('')
    const handleAdd=()=>{
        list.value.push(a.value)
        a.value=''
    } 
    defineExpose({ list })
</script>
五,provide/inject
provide和inject是Vue中提供的一对API,该API可以实现父组件向子组件传递数据,无论层级有多深,都可以通过这对API实现

父组件

<template>
    <div class="home">
        <child></child>
        <div>
            <input v-model="value" type="text" placeholder="输入"/>
            <button @click="handleAdd" type="button">添加</button>
        </div>
    </div>
</template>
 
<script setup lang="ts">
    import child from "./homr/index.vue"
    import { ref, provide} from "vue";
    const list = ref (['JavaScript', 'HTML', 'CSS'])
    const msg=ref('父组件的值');
    provide('list',list.value)
    const handleAdd = () =>{
        list.value.push(msg.value)
        msg.value=''
    }
</script>
子组件

使用provide进行数据传递时,尽量readonly进行数据包装,避免子组件修改父级传递过去的数据

<template>
        <div >
            <div v-for="a in props" :key="a">{{ a }}</div>
        </div>
</template>
    
<script setup lang='ts'>
    import { inject } from 'vue'
    const props =inject('list')
</script>
六,mitt
mitt.js  原理是EventBus 跨组件通信,

先安装 npm i mitt -S

然后在封装一下

//mitt.js
import mitt from 'mitt'
const mitt = mitt()
export default mitt
// 组件 A
<script setup>
import mitt from './mitt'
const handleClick = () => {
    mitt.emit('handleChange')
}
</script>
 
// 组件 B
<script setup>
import mitt from './mitt'
import { onUnmounted } from 'vue'
const someMethed = () => { ... }
mitt.on('handleChange',someMethed)
onUnmounted(()=>{
    mitt.off('handleChange',someMethed)
})
</script>
七,pinia
pinia 和 vuex 具有相同的功效, 是 Vue 的存储库,它允许您跨组件/页面共享状态。
设计使用的是 Composition api,更符合vue3的设计思维。
Pinia 对 Vue 2 和 Vue 3 都有效,并且不需要您使用组合 API。

1.pinia 符合直觉,易于学习。
2.pinia 是轻量级状态管理工具,大小只有1KB.
3.pinia 模块化设计,方便拆分。
4.pinia 没有 mutations,直接在 actions 中操作 state,通过 this.xxx 访问响应的状态,尽管可 以直接操作 state,但是还是推荐在 actions 中操作,保证状态不被意外的改变。
5.store 的 action 被调度为常规的函数调用,而不是使用 dispatch 方法或者是 MapAction 辅助函数,这是在 Vuex 中很常见的。
6.支持多个 store。
7.支持 Vue devtools、SSR、webpack 代码拆分。

安装npm包

npm install pinia --save         

在main.js中 导入

import { createPinia } from 'pinia'

app.use(createPinia())

使用

//在src目录下,像vuex一样创建store文件夹,文件夹下面创建index.js
import { defineStore } from 'pinia'
//这个函数的第一个参数为他的id,这个id必须是唯一的
export const useMainStore = defineStore('main', {
    state: () => {
        return{
            count:0
        }
    },
    getters: {},
    actions: {
        increment() {
            this.count++
        }
    }
})
 

<template>
     {{mainStore.count}}
    <button @click="mainFn">13</button>
</template>
<script setup>
import {useMainStore} from '@/pinia-store/index'
const mainStore = useMainStore()
//改变count的值
const mainFn = ()=>{
    //第一种方式
    mainStore.count++
    //第二种方式
    mainStore.increment()
    //第三种方式
    mainStore.$patch({
        count : mainStore.count + 1
     })
    //第四种方式
    mainStore.$patch( state =>{
           state.count++
      })
}
//重置状态
mainStore.$reset()
mainStore.$state = {
   count : 0
}
</script>
                
      
————————————————

                

                           

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

Vue3中,有多种组件通信方式: - **useAttrs方法**:可以利用useAttrs方法获取组件的属性与事件(包含原生DOM事件或者自定义事件),此函数功能类似于Vue2框架中`attrs`属性与`listeners`方法 [^2]。 - **全局状态管理库Pinia**:和Vue2的vuex类似,是一个全局状态管理库,更符合视觉,它的store直接支持组合式写法。示例代码如下: ```javascript import {defineStore} from &#39;pinia&#39; import axios from &#39;axios&#39; import {nanoid} from &#39;nanoid&#39; import {reactive} from &#39;vue&#39; export const useTalkStore = defineStore(&#39;talk&#39;,() => { // talkList就是state const talkList = reactive( JSON.parse(localStorage.getItem(&#39;talkList&#39;) as string) || [] ) // getATalk函数相当于action async function getATalk(){ // 发请求,下面这行的写法是:连续解构赋值+重命名 let {data:{content:title}} = await axios.get(&#39;https://api.uomg.com/api/rand.qinghua?format=json&#39;) // 把请求回来的字符串,包装成一个对象 let obj = {id:nanoid(),title} // 放到数组中 talkList.unshift(obj) } return {talkList,getATalk} }) ``` [^3] - **子组件调用父组件传过来的方法传递数据**:子组件通过调用父组件传过来的方法传递数据给父组件。示例代码如下: ```vue <!-- Father.vue --> <template> <div id="app"> <img alt="Vue logo" src="./assets/logo.png"> <h1>sonValue:{{sonValue}}</h1> <Son msg="这是父组件传过来的数据" @receiveValue="receiveValue" /> </div> </template> <script> import Son from &#39;./components/Son.vue&#39; export default { name: &#39;App&#39;, data() { return {sonValue: &#39;&#39;} }, components: { Son }, methods: { receiveValue(data) { this.sonValue = data; } } } </script> ``` [^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值