最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文詳解Vue3中的14種組件通信方式

 更新時(shí)間:2025年01月10日 10:46:41   作者:程序員小寒  
對(duì)于日常使用vue3開發(fā)項(xiàng)目的前端小伙伴來(lái)說(shuō),組件通信方式可以說(shuō)是必會(huì)的基本功,今天帶大家一起盤下vue3中的14種通信方式,希望對(duì)大家有所幫助

對(duì)于日常使用vue3開發(fā)項(xiàng)目的前端小伙伴來(lái)說(shuō),組件通信方式可以說(shuō)是必會(huì)的基本功,今天帶大家一起盤下vue3的通信方式。

我們按照組件的關(guān)系來(lái)劃分??偣舶?4中組件通信方式。

一:父子通信

1.1、父?jìng)髯樱簆rops

最最常用的通信方式是props了,父組件通過(guò)props方式將屬性傳遞給子組件,子組件接受props并用于數(shù)據(jù)操作和頁(yè)面渲染。

注意:子組件不要直接修改父組件傳遞過(guò)來(lái)的props,保持自上而下單項(xiàng)數(shù)據(jù)流,這樣會(huì)讓數(shù)據(jù)的流向十分清晰,方便后續(xù)維護(hù)!

// Parent.vue
<template>
   <Child :msg="msg"/>
</template>

<script setup>
import { ref } from 'vue';
import Child from './components/Child.vue';

const msg = ref('hello world');
</script>
// Child.vue
<template>
    <div>
        propsData:{{ msg }}
    </div>
</template>

<script setup>
defineProps({
    msg: String
})
</script>

1.2、子傳父:defineEmits

通過(guò)defineEmits可以讓子組件的值傳遞到父組件中。

其用法如下:

先在子組件中用defineEmits([...emitName])定義一個(gè)或多個(gè)emit,它的返回值是一個(gè)emits函數(shù),然后可以通過(guò)調(diào)用emits函數(shù)向父組件發(fā)射時(shí)間,并攜帶參數(shù)。

// Child.vue
<template>
    <div @click="onClick">
        child
    </div>
</template>

<script setup>
const emits = defineEmits(['update']);
const onClick = () => {
    emits('update', 'child update');
}
</script>

在父組件中通過(guò)@符 + 事件名監(jiān)聽子組件發(fā)射 出來(lái)的事件,并接收其傳過(guò)來(lái)的值。

// Parent.vue
<template>
    <div>
        Parent
        <Child @update="update"/>
    </div>
</template>

<script setup>
import Child from './Child.vue';
const update = val => {
    console.log(val); // 當(dāng)子組件點(diǎn)擊事件觸發(fā)后,這里會(huì)打印 child update
}
</script>

vue2的組件中還可以通過(guò)this.$on、this.$emit來(lái)監(jiān)聽、發(fā)射事件,以達(dá)到傳值的目的,但在vue3中已廢棄這種寫法。

1.3、$attrs

如果需要在子組件中接收的props很多,如果在props聲明比較繁瑣,所以vue給我們提供了一個(gè)優(yōu)雅的解決方案,即$attrs,$attrs指的是父組件傳遞給子組件的所有屬性中,剔除在props中定義的那部分之后,剩下的就會(huì)放在$attrs中。

舉個(gè)例子:

// Parent.vue
<template>
    <div>
        Parent
       <Child :msg1="1" :msg2="2" />
    </div>
</template>

這里父組件給子組件傳遞了兩個(gè)屬性msg1、msg2。

// Child.vue
<template>
    <div>
        child: {{ $attrs }}
    </div>
</template>

<script setup>
defineProps({
    msg1: String
})
</script>

這里子組件使用了defineProps定義了msg1,則頁(yè)面中$attrs的值為{ msg2: 2 }

還可以使用v-bind$attrs的所有數(shù)據(jù),以屬性的方式全部傳遞到子組件中,我們平常在封裝組件的時(shí)候,這個(gè)東西就能幫助我們實(shí)現(xiàn)組件的屬性透?jìng)鳎趾糜谩?/p>

<template>
    <Child v-bind="$attrs"/>
</template>

注意:在vue3中$listeners已廢棄,無(wú)法使用。

1.4、$ref + defineExpose

通過(guò)$ref可以拿到組件的實(shí)例,defineExpose可以顯式指定在 <script setup> 組件中要暴露出去的屬性,它兩一起配合使用,就能實(shí)現(xiàn)父子組件的通信。

其用法如下:

在子組件中通過(guò)defineExpose暴露一個(gè)update方法。

// Child.vue
<script setup>
defineExpose({
    update(val) {
        console.log('父組件傳遞過(guò)來(lái)的值', val);
    }
})
</script>

在父組件中通過(guò)ref拿到組件實(shí)例并調(diào)用子組件暴露的update方法。

// Parent.vue
<template>
    <div>
        Parent
       <Child ref="childRef"/>
    </div>
</template>

<script setup>
import Child from './Child.vue';
import { ref, onMounted } from 'vue';

const childRef = ref(null);

onMounted(() => {
    childRef.value.update('hello')
})
const update = () => {}

</script>

1.5、$parent

$parent代表當(dāng)前組件的父組件實(shí)例,如果當(dāng)前組件是頂層組件,則$parent的值為null

我們可以通過(guò)$parent拿到父組件的實(shí)例,自然就可以進(jìn)行父子組件的交互了。一般也是和defineExpose配合使用,和$ref + defineExpose用法類似,這里就不多說(shuō)了。

注意:$children在vue3中已經(jīng)廢棄,無(wú)法使用。

1.6、作用域插槽

通過(guò)作用域插槽可以實(shí)現(xiàn)子組件向父組件傳遞數(shù)據(jù)。

子組件代碼

<template>
    <div>
      <slot :data="{ a:1, b: 2 }"/>
    </div>
</template>

子組件可以在slot標(biāo)簽上傳遞數(shù)據(jù)給父組件。

父組件代碼

<template>
    <Child>
        <template v-slot="slotProps">
        {{ slotProps.data }}
        </template>
    </Child>
</template>
<script setup>
import Child from './Child.vue';
</script>

父組件用v-slot來(lái)接收數(shù)據(jù),并渲染到頁(yè)面上。

1.7、v-model

v-model可以在組件上使用以實(shí)現(xiàn)雙向綁定,vue內(nèi)部會(huì)幫你傳遞值和綁定事件,也是達(dá)到了父子組件通訊的效果。

vue3.4開始,還可以使用defineModel便利宏,其用法如下:

子組件代碼

// Child.vue
<template>
    <div>model的值: {{ model }}</div>
    <button @click="handleClick">+1</button>
  </template>

<script setup>
const model = defineModel()

function handleClick() {
  model.value++
}
</script>

父組件代碼

// Parent.vue
<template>
    <Child1 v-model="modelValue"></Child1>
    Parent:{{ modelValue }}
</template>

<script setup>
import Child from './Child.vue';
const modelValue = ref(0)
</script>

defineModel的返回值就是一個(gè)ref,你可以隨意訪問(wèn)和修改它,并且它會(huì)和父組件的v-model綁定的值保持同步,也就是實(shí)現(xiàn)了雙向綁定。

二、兄弟組件

兩個(gè)兄弟關(guān)系組件進(jìn)行通信,我們一般會(huì)借助第三方媒介。

2.1、mitt

mitt相當(dāng)于我們vue2的事件總線$bus,只是vue3將其廢棄,所以我們借助mitt實(shí)現(xiàn)類似$bus的效果。

用法如下:

安裝mitt

npm install mitt

初始化mitt

// emitter.js
import mitt from'mitt';
export default mitt();

兄弟組件1:

<script setup>
import emitter from '@/utils/emitter'
emitter.on('update', (val) => {
  console.log('update事件觸發(fā)', val)
})
</script>

兄弟組件2:

<script setup>
import emitter from '@/utils/emitter'

setTimeout(() => {
  emitter.emit('update', 'hello')
}, 1000)
</script>

2.2、$parent

我們可以把狀態(tài)(即數(shù)據(jù))定義在父組件中,兩個(gè)兄弟組件可以借助其共同的父組件共享同一份數(shù)據(jù),間接實(shí)現(xiàn)通信。

2.3、vuex/pinia

vuexvue官方提供的狀態(tài)管理工具,用它可以實(shí)現(xiàn)全局的狀態(tài)共享,自然也可以實(shí)現(xiàn)兄弟組件的通信了。當(dāng)然也可以使用pinia替代vuex。

2.4、app.config.globalProperties

app.config.globalProperties是一個(gè)全局的對(duì)象,在應(yīng)用內(nèi)所有組件實(shí)例都能訪問(wèn)到,當(dāng)組件屬性名和它發(fā)生同名沖突時(shí),采取就近原則,以組件的為準(zhǔn),這個(gè)就相當(dāng)于vue2Vue.prototype

三、跨層級(jí)通信

3.1、mitt

mitt可以實(shí)現(xiàn)全局的通信,這個(gè)在上面介紹兄弟組件通信的時(shí)候已經(jīng)說(shuō)過(guò),這里不再多說(shuō)了。

3.2、vuex/pinia

vuexpinia都是全局的狀態(tài)管理工具,跨層級(jí)通信也不再話下。

3.3、provide/inject

provide/injectvue3提供的可以跨層級(jí)通信的方式。

其用法如下:

父組件/根組件中定義provide提供數(shù)據(jù)。

// App.vue
<script setup>
import { ref, provide } from 'vue';

const name = ref('sam');
provide('name', name)
</script>

子組件/孫子組件中使用inject,注入數(shù)據(jù)。

// 后代組件
<script setup>
import { inject } from 'vue';

const name = inject('name');
console.log('name', name.value); // 輸出name
</script>

四、其它方式

4.1、瀏覽器本地存儲(chǔ)storage

html5提供了一套storage API,包括了localStoragesessionStorage,它實(shí)現(xiàn)持久化存儲(chǔ)、緩存等功能,自然也可以用來(lái)組件間通信了。

// 組件A
<script setup>
sessionStorage.setItem('name', 'jack');
</script>
// 組件B
<script setup>
setTimeout(() => {
  console.log(sessionStorage.getItem('name')); //打印 jack
}, 1000)
</script>

這里我在組件A使用sessionStarge設(shè)置了一個(gè)name值,在組件B里面就能拿到了,只要保證獲取值在設(shè)置值之后執(zhí)行就行了。

4.2、全局window對(duì)象(不推薦使用)

window作為一個(gè)全局對(duì)象,當(dāng)然也可以使用它來(lái)通信了,不過(guò)它既然誰(shuí)都可以訪問(wèn)到,就存在如下問(wèn)題:

  • 命令沖突問(wèn)題;
  • 難以追蹤數(shù)據(jù)修改,可維護(hù)性差;
  • 掛在window上的數(shù)據(jù)難以銷毀,從而造成內(nèi)存泄漏。

所以不推薦使用window對(duì)象進(jìn)行通信。

4.3、 ES6模塊化import/export

我們可以使用ES5的模塊化規(guī)范import/export實(shí)現(xiàn)通信。

// a.js
export let a = undefined;
setTimeout(() => {
  a = 1;
}, 1000)
// b.js
import { a } from './a.js'

setTimeout(() => {
  console.log(a); // 打印1
}, 2000)

由于ES module采用的是符號(hào)綁定,所以就算export的值是一個(gè)基本數(shù)據(jù)類型的值,后續(xù)修改了也能訪問(wèn)到。

以上就是一文詳解Vue3中的14種組件通信方式的詳細(xì)內(nèi)容,更多關(guān)于Vue3組件通信方式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue3基于elementplus 簡(jiǎn)單實(shí)現(xiàn)表格二次封裝過(guò)程

    vue3基于elementplus 簡(jiǎn)單實(shí)現(xiàn)表格二次封裝過(guò)程

    公司渲染表格數(shù)據(jù)時(shí)需要將空數(shù)據(jù)顯示‘-’,并且對(duì)于每一列數(shù)據(jù)的顯示也有一定的要求,基于這個(gè)需求對(duì)element-plus簡(jiǎn)單進(jìn)行了二次封裝,這篇文章主要介紹了vue3基于elementplus 簡(jiǎn)單實(shí)現(xiàn)表格二次封裝過(guò)程,需要的朋友可以參考下
    2024-05-05
  • 前端vue3項(xiàng)目中百度地圖的使用api以及操作實(shí)例

    前端vue3項(xiàng)目中百度地圖的使用api以及操作實(shí)例

    最近項(xiàng)目要用到百度地圖api,好久沒(méi)用到地圖,就百度了一番,但是找了好幾篇文章,發(fā)現(xiàn)都沒(méi)辦法成功實(shí)現(xiàn),現(xiàn)將方法記錄如下,下面這篇文章主要給大家介紹了關(guān)于前端vue3項(xiàng)目中百度地圖的使用api以及操作實(shí)例,需要的朋友可以參考下
    2023-05-05
  • vue的表單數(shù)據(jù)收集案例之基本指令和自定義指令詳解

    vue的表單數(shù)據(jù)收集案例之基本指令和自定義指令詳解

    收集表單數(shù)據(jù)可以使用這個(gè)v-model實(shí)現(xiàn)這個(gè)數(shù)據(jù)的綁定,但是在有些輸入框中,還需要一些其他的指令搭配這個(gè)v-model指令結(jié)合使用,這篇文章主要介紹了vue的表單數(shù)據(jù)收集,基本指令和自定義指令,需要的朋友可以參考下
    2023-01-01
  • vue實(shí)現(xiàn)app頁(yè)面切換動(dòng)畫效果實(shí)例

    vue實(shí)現(xiàn)app頁(yè)面切換動(dòng)畫效果實(shí)例

    本篇文章主要介紹了vue實(shí)現(xiàn)app頁(yè)面切換動(dòng)畫效果實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Vue包大小優(yōu)化的實(shí)現(xiàn)(從1.72M到94K)

    Vue包大小優(yōu)化的實(shí)現(xiàn)(從1.72M到94K)

    這篇文章主要介紹了Vue包大小優(yōu)化的實(shí)現(xiàn)(從1.72M到94K),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • Vue+ElementUI之Tree的使用方法

    Vue+ElementUI之Tree的使用方法

    這篇文章主要為大家詳細(xì)介紹了Vue+ElementUI之Tree的使用方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • Vue Router中應(yīng)用中間件的方法

    Vue Router中應(yīng)用中間件的方法

    這篇文章主要介紹了Vue Router中應(yīng)用中間件的方法,文中講解非常細(xì)致,幫助大家更好的理解和學(xué)習(xí)vue router,感興趣的朋友可以了解下
    2020-08-08
  • Vue基于el-breadcrumb實(shí)現(xiàn)面包屑功能(操作代碼)

    Vue基于el-breadcrumb實(shí)現(xiàn)面包屑功能(操作代碼)

    這篇文章主要介紹了Vue基于el-breadcrumb實(shí)現(xiàn)面包屑功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-09-09
  • 關(guān)于在vue 中使用百度ueEditor編輯器的方法實(shí)例代碼

    關(guān)于在vue 中使用百度ueEditor編輯器的方法實(shí)例代碼

    這篇文章主要介紹了在vue 中使用百度ueEditor編輯器的方法實(shí)例代碼 ,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-09-09
  • Vue 通過(guò)公共字段,拼接兩個(gè)對(duì)象數(shù)組的實(shí)例

    Vue 通過(guò)公共字段,拼接兩個(gè)對(duì)象數(shù)組的實(shí)例

    今天小編就為大家分享一篇Vue 通過(guò)公共字段,拼接兩個(gè)對(duì)象數(shù)組的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-11-11

最新評(píng)論

清远市| 仙桃市| 博湖县| 罗山县| 广安市| 永善县| 会理县| 抚顺市| 安龙县| 阿拉善盟| 蓬莱市| 井研县| 齐齐哈尔市| 榕江县| 库伦旗| 日照市| 高要市| 昌乐县| 克拉玛依市| 泽普县| 东城区| 神农架林区| 岫岩| 乐至县| 绥芬河市| 都江堰市| 福安市| 百色市| 乐平市| 屏南县| 新源县| 壶关县| 平阳县| 长沙市| 丹东市| 宣武区| 天祝| 江安县| 保康县| 永州市| 塔城市|