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

Vue3 子傳父全解析實(shí)戰(zhàn)

 更新時(shí)間:2026年02月18日 09:31:06   作者:不想禿頭的程序員  
組件通信是繞不開的核心場景,而子傳父作為最基礎(chǔ)、最常用的通信方式之一,更是新手入門必掌握的知識(shí)點(diǎn),文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

在 Vue3 開發(fā)中,組件通信是繞不開的核心場景,而子傳父作為最基礎(chǔ)、最常用的通信方式之一,更是新手入門必掌握的知識(shí)點(diǎn)。不同于 Vue2 的 $emit 寫法,Vue3 組合式 API(<script setup>)簡化了子傳父的實(shí)現(xiàn)邏輯,但也有不少細(xì)節(jié)和進(jìn)階技巧需要注意。

本文將拋開 TypeScript,用最通俗的語言 + 可直接復(fù)制的實(shí)戰(zhàn)代碼,從基礎(chǔ)用法、進(jìn)階技巧、常見場景到避坑指南,全方位講解 Vue3 子傳父,新手看完就能上手,老手也能查漏補(bǔ)缺。

一、核心原理:子組件觸發(fā)事件,父組件監(jiān)聽事件

Vue3 子傳父的核心邏輯和 Vue2 一致:子組件通過觸發(fā)自定義事件,將數(shù)據(jù)傳遞給父組件;父組件通過監(jiān)聽該自定義事件,接收子組件傳遞的數(shù)據(jù)。

關(guān)鍵區(qū)別在于:Vue3 <script setup> 中,無需通過 this.$emit 觸發(fā)事件,而是通過 defineEmits 聲明事件后,直接調(diào)用 emit 函數(shù)即可,語法更簡潔、更直觀。

先記住核心流程,再看具體實(shí)現(xiàn):

  1. 子組件:用 defineEmits 聲明要觸發(fā)的自定義事件(可選但推薦);
  2. 子組件:在需要傳值的地方(如點(diǎn)擊事件、接口回調(diào)),調(diào)用 emit('事件名', 要傳遞的數(shù)據(jù));
  3. 父組件:在使用子組件的地方,通過 @事件名="處理函數(shù)" 監(jiān)聽事件;
  4. 父組件:在處理函數(shù)中,接收子組件傳遞的數(shù)據(jù)并使用。

二、基礎(chǔ)用法:最簡潔的子傳父實(shí)現(xiàn)(必學(xué))

我們用一個(gè)「子組件輸入內(nèi)容,父組件實(shí)時(shí)顯示」的簡單案例,講解基礎(chǔ)用法,代碼可直接復(fù)制到項(xiàng)目中運(yùn)行。

1. 子組件(Child.vue):聲明事件 + 觸發(fā)事件

<template>
  <div class="child">
    <h4>我是子組件</h4>
    <!-- 輸入框輸入內(nèi)容,觸發(fā)input事件,傳遞輸入值 -->
    <input 
      type="text" 
      v-model="childInput" 
      @input="handleInput"
      placeholder="請輸入要傳遞給父組件的內(nèi)容"
    />
    <!-- 按鈕點(diǎn)擊,傳遞固定數(shù)據(jù) -->
    <button @click="handleClick" style="margin-top: 10px;">
      點(diǎn)擊向父組件傳值
    </button>
  </div>
</template>

<script setup>
// 1. 聲明要觸發(fā)的自定義事件(數(shù)組形式,元素是事件名)
// 可選,但推薦聲明:增強(qiáng)代碼可讀性,IDE會(huì)有語法提示,避免拼寫錯(cuò)誤
const emit = defineEmits(['inputChange', 'btnClick'])

// 子組件內(nèi)部數(shù)據(jù)
const childInput = ref('')

// 輸入框變化時(shí),觸發(fā)事件并傳遞輸入值
const handleInput = () => {
  // 2. 觸發(fā)事件:第一個(gè)參數(shù)是事件名,第二個(gè)參數(shù)是要傳遞的數(shù)據(jù)(可選,可多個(gè))
  emit('inputChange', childInput.value)
}

// 按鈕點(diǎn)擊時(shí),觸發(fā)事件并傳遞固定對(duì)象
const handleClick = () => {
  emit('btnClick', {
    name: '子組件',
    msg: '這是子組件通過點(diǎn)擊按鈕傳遞的數(shù)據(jù)'
  })
}
</script>

2. 父組件(Parent.vue):監(jiān)聽事件 + 接收數(shù)據(jù)

<template>
  <div class="parent">
    <h3>我是父組件</h3>
    <p>子組件輸入的內(nèi)容:{{ parentMsg }}</p>
    <p>子組件點(diǎn)擊傳遞的數(shù)據(jù):{{ parentData }}</p>
    
    <!-- 3. 監(jiān)聽子組件聲明的自定義事件,綁定處理函數(shù) -->
    <Child 
      @inputChange="handleInputChange"
      @btnClick="handleBtnClick"
    />
  </div>
</template>

<script setup>
// 引入子組件
import Child from './Child.vue'
import { ref, reactive } from 'vue'

// 父組件接收數(shù)據(jù)的容器
const parentMsg = ref('')
const parentData = reactive({
  name: '',
  msg: ''
})

// 4. 處理子組件觸發(fā)的inputChange事件,接收傳遞的數(shù)據(jù)
const handleInputChange = (val) => {
  // val 就是子組件emit傳遞過來的值(childInput.value)
  parentMsg.value = val
}

// 處理子組件觸發(fā)的btnClick事件,接收傳遞的對(duì)象
const handleBtnClick = (data) => {
  // data 是子組件傳遞的對(duì)象,直接解構(gòu)或賦值即可
  parentData.name = data.name
  parentData.msg = data.msg
}
</script>

3. 核心細(xì)節(jié)說明

  • defineEmits 是 Vue3 內(nèi)置的宏,無需導(dǎo)入,可直接使用;
  • emit 函數(shù)的第一個(gè)參數(shù)必須和 defineEmits 中聲明的事件名一致(大小寫敏感),否則父組件無法監(jiān)聽到;
  • emit 可傳遞多個(gè)參數(shù),比如 emit('event', val1, val2),父組件處理函數(shù)可對(duì)應(yīng)接收 (val1, val2) => {}
  • 父組件監(jiān)聽事件時(shí),可使用 @事件名(簡寫)或 v-on:事件名(完整寫法),效果一致。

三、進(jìn)階用法:優(yōu)化子傳父的體驗(yàn)(實(shí)戰(zhàn)常用)

基礎(chǔ)用法能滿足簡單場景,但在實(shí)際開發(fā)中,我們還會(huì)遇到「事件校驗(yàn)」「雙向綁定」「事件命名規(guī)范」等需求,這部分進(jìn)階技巧能讓你的代碼更規(guī)范、更健壯。

1. 事件校驗(yàn):限制子組件傳遞的數(shù)據(jù)類型

通過 defineEmits 的對(duì)象形式,可對(duì)事件傳遞的數(shù)據(jù)進(jìn)行類型校驗(yàn),避免子組件傳遞錯(cuò)誤類型的數(shù)據(jù),提升代碼可靠性(類似 props 校驗(yàn))。

<script setup>
// 對(duì)象形式聲明事件,key是事件名,value是校驗(yàn)函數(shù)(參數(shù)是子組件傳遞的數(shù)據(jù),返回boolean)
const emit = defineEmits({
  // 校驗(yàn)inputChange事件傳遞的數(shù)據(jù)必須是字符串
  inputChange: (val) => {
    return typeof val === 'string'
  },
  // 校驗(yàn)btnClick事件傳遞的數(shù)據(jù)必須是對(duì)象,且包含name和msg屬性
  btnClick: (data) => {
    return typeof data === 'object' && 'name' in data && 'msg' in data
  }
})

// 若傳遞的數(shù)據(jù)不符合校驗(yàn),控制臺(tái)會(huì)報(bào)警告(不影響代碼運(yùn)行,僅提示)
const handleInput = () => {
  emit('inputChange', 123) // 傳遞數(shù)字,不符合校驗(yàn),控制臺(tái)報(bào)警告
}
</script>

2. 雙向綁定:v-model 簡化子傳父(高頻場景)

很多時(shí)候,子傳父是為了「修改父組件的數(shù)據(jù)」,比如表單組件、開關(guān)組件,這時(shí)可使用 v-model 簡化代碼,實(shí)現(xiàn)父子組件雙向綁定,無需手動(dòng)聲明事件和處理函數(shù)。

Vue3 中,v-model 本質(zhì)是「語法糖」,等價(jià)于 :modelValue="xxx" @update:modelValue="xxx = $event"。

優(yōu)化案例:子組件開關(guān),父組件顯示狀態(tài)

<!-- 子組件(Child.vue) -->
<template>
  <div class="child">
    <h4>子組件開關(guān)</h4>
    <button @click="handleSwitch">
      {{ isOpen ? '關(guān)閉' : '打開' }}
    </button>
  </div>
</template>

<script setup>
// 1. 接收父組件通過v-model傳遞的modelValue
const props = defineProps(['modelValue'])
// 2. 聲明update:modelValue事件(固定命名,不可修改)
const emit = defineEmits(['update:modelValue'])

// 子組件內(nèi)部使用父組件傳遞的值
const isOpen = computed(() => props.modelValue)

// 開關(guān)切換,觸發(fā)事件,修改父組件數(shù)據(jù)
const handleSwitch = () => {
  emit('update:modelValue', !isOpen.value)
}
</script>
<!-- 父組件(Parent.vue) -->
<template>
  <div class="parent">
    <h3>父組件:{{ isSwitchOpen ? '開關(guān)已打開' : '開關(guān)已關(guān)閉' }}</h3>
    <!-- 直接使用v-model,無需手動(dòng)監(jiān)聽事件 -->
    <Child v-model="isSwitchOpen" />
  </div>
</template>

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

const isSwitchOpen = ref(false)
</script>

擴(kuò)展:多個(gè) v-model 雙向綁定

Vue3 支持給同一個(gè)子組件綁定多個(gè) v-model,只需給 v-model 加后綴,對(duì)應(yīng)子組件的propsemit 即可。

<!-- 父組件 -->
<Child 
  v-model:name="parentName" 
  v-model:age="parentAge" 
/>

<!-- 子組件 -->
<script setup>
// 接收多個(gè)v-model傳遞的props
const props = defineProps(['name', 'age'])
// 聲明對(duì)應(yīng)的update事件
const emit = defineEmits(['update:name', 'update:age'])

// 觸發(fā)事件修改父組件數(shù)據(jù)
emit('update:name', '新名字')
emit('update:age', 25)
</script>

3. 事件命名規(guī)范:提升代碼可讀性

在實(shí)際開發(fā)中,遵循統(tǒng)一的事件命名規(guī)范,能讓團(tuán)隊(duì)協(xié)作更高效,推薦以下規(guī)范:

  • 事件名采用「kebab-case 短橫線命名」(和 HTML 事件命名一致),比如 input-change 而非 inputChange;
  • 事件名要語義化,體現(xiàn)事件的用途,比如 form-submit(表單提交)、delete-click(刪除點(diǎn)擊);
  • 雙向綁定的事件固定為 update:xxx,xxx 對(duì)應(yīng) props 名,比如 update:name、update:visible。

四、實(shí)戰(zhàn)場景:子傳父的常見應(yīng)用

結(jié)合實(shí)際開發(fā)中的高頻場景,給大家補(bǔ)充 3 個(gè)常用案例,覆蓋大部分子傳父需求。

場景1:子組件表單提交,父組件接收表單數(shù)據(jù)

<!-- 子組件(FormChild.vue) -->
<template>
  <div class="form-child">
    <input v-model="form.name" placeholder="請輸入姓名" />
    <input v-model="form.age" type="number" placeholder="請輸入年齡" />
    <button @click="handleSubmit">提交表單</button>
  </div>
</template>

<script setup>
import { reactive } from 'vue'

const emit = defineEmits(['form-submit'])

const form = reactive({
  name: '',
  age: ''
})

const handleSubmit = () => {
  // 表單校驗(yàn)(簡化)
  if (!form.name || !form.age) return alert('請?zhí)顚懲暾畔?)
  // 提交表單數(shù)據(jù)給父組件
  emit('form-submit', form)
  // 提交后重置表單
  form.name = ''
  form.age = ''
}
</script>

場景2:子組件關(guān)閉彈窗,父組件控制彈窗顯示/隱藏

<!-- 子組件(ModalChild.vue) -->
<template>
  <div class="modal" v-if="visible">
    <div class="modal-content">
      <h4>子組件彈窗</h4>
      <button @click="handleClose">關(guān)閉彈窗</button>
    </div>
  </div>
</template>

<script setup>
const props = defineProps(['visible'])
const emit = defineEmits(['close-modal'])

const handleClose = () => {
  // 觸發(fā)關(guān)閉事件,通知父組件隱藏彈窗
  emit('close-modal')
}
</script>

場景3:子組件列表刪除,父組件更新列表

<!-- 子組件(ListChild.vue) -->
<template>
  <div class="list-child">
    <div v-for="item in list" :key="item.id">
      {{ item.name }}
      <button @click="handleDelete(item.id)">刪除</button>
    </div>
  </div>
</template>

<script setup>
const props = defineProps(['list'])
const emit = defineEmits(['delete-item'])

const handleDelete = (id) => {
  // 傳遞要?jiǎng)h除的id給父組件,由父組件更新列表
  emit('delete-item', id)
}
</script>

五、常見坑點(diǎn)避坑指南(新手必看)

很多新手在寫子傳父時(shí),會(huì)遇到「父組件監(jiān)聽不到事件」「數(shù)據(jù)傳遞失敗」等問題,以下是最常見的 4 個(gè)坑點(diǎn),幫你快速避坑。

坑點(diǎn)1:事件名大小寫不一致

子組件 emit('inputChange'),父組件 @inputchange="handle"(小寫),會(huì)導(dǎo)致父組件監(jiān)聽不到事件。

解決方案:統(tǒng)一采用 kebab-case 命名,子組件 emit('input-change'),父組件 @input-change="handle"。

坑點(diǎn)2:忘記聲明事件(defineEmits)

子組件直接調(diào)用 emit('event'),未用 defineEmits 聲明事件,雖然開發(fā)環(huán)境可能不報(bào)錯(cuò),但生產(chǎn)環(huán)境可能出現(xiàn)異常,且 IDE 無提示。

解決方案:無論事件是否需要校驗(yàn),都用 defineEmits 聲明(數(shù)組形式即可)。

坑點(diǎn)3:傳遞復(fù)雜數(shù)據(jù)(對(duì)象/數(shù)組)時(shí),父組件修改后影響子組件

子組件傳遞對(duì)象/數(shù)組給父組件,父組件直接修改該數(shù)據(jù),會(huì)影響子組件(因?yàn)橐妙愋蛡鬟f的是地址)。

解決方案:父組件接收數(shù)據(jù)后,用 JSON.parse(JSON.stringify(data)) 深拷貝,或用 reactive + toRaw 處理,避免直接修改原始數(shù)據(jù)。

坑點(diǎn)4:v-model 雙向綁定時(shí)報(bào)錯(cuò),提示「modelValue 未定義」

原因:子組件未接收 modelValue props,或未聲明 update:modelValue 事件。

解決方案:確保子組件 defineProps(['modelValue'])defineEmits(['update:modelValue']) 都聲明。

六、總結(jié):子傳父核心要點(diǎn)回顧

Vue3 子傳父的核心就是「事件觸發(fā) + 事件監(jiān)聽」,記住以下 3 個(gè)核心要點(diǎn),就能應(yīng)對(duì)所有場景:

  1. 基礎(chǔ)寫法:defineEmits 聲明事件 → emit 觸發(fā)事件 → 父組件 @事件名 監(jiān)聽;
  2. 進(jìn)階優(yōu)化:事件校驗(yàn)提升可靠性,v-model 簡化雙向綁定,遵循 kebab-case 命名規(guī)范;
  3. 避坑關(guān)鍵:事件名大小寫一致、必聲明事件、復(fù)雜數(shù)據(jù)深拷貝、v-model 對(duì)應(yīng) props 和 emit 命名正確。

子傳父是 Vue3 組件通信中最基礎(chǔ)的方式,掌握它之后,再學(xué)習(xí)父傳子(props)、跨層級(jí)通信(provide/inject)、全局通信(Pinia)會(huì)更輕松。

到此這篇關(guān)于Vue3 子傳父全解析實(shí)戰(zhàn)的文章就介紹到這了,更多相關(guān)Vue3 子傳父內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • VUEJS實(shí)戰(zhàn)之修復(fù)錯(cuò)誤并且美化時(shí)間(2)

    VUEJS實(shí)戰(zhàn)之修復(fù)錯(cuò)誤并且美化時(shí)間(2)

    這篇文章主要為大家詳細(xì)介紹了VUEJS實(shí)戰(zhàn)之修復(fù)錯(cuò)誤并且美化時(shí)間,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-06-06
  • vue下使用fullcalendar案例講解

    vue下使用fullcalendar案例講解

    這篇文章主要介紹了vue下使用fullcalendar及簡單案例,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2024-01-01
  • Vue2 添加數(shù)據(jù)可視化支持的方法步驟

    Vue2 添加數(shù)據(jù)可視化支持的方法步驟

    這篇文章主要介紹了Vue2 添加數(shù)據(jù)可視化支持的方法步驟,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-01-01
  • vue 父組件通過$refs獲取子組件的值和方法詳解

    vue 父組件通過$refs獲取子組件的值和方法詳解

    今天小編就為大家分享一篇vue 父組件通過$refs獲取子組件的值和方法詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11
  • elementui實(shí)現(xiàn)表格自定義排序的示例代碼

    elementui實(shí)現(xiàn)表格自定義排序的示例代碼

    本文主要介紹了elementui實(shí)現(xiàn)表格自定義排序的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • vue和react中關(guān)于插槽詳解

    vue和react中關(guān)于插槽詳解

    這篇文章主要介紹了vue和react中關(guān)于插槽詳解,slot插槽是Vue對(duì)組件嵌套這種擴(kuò)展機(jī)制的稱謂,在react可以也這樣稱呼,但是并不很常見。不過叫slot確實(shí)很形象
    2022-08-08
  • el-select 點(diǎn)擊按鈕滾動(dòng)到選擇框頂部的實(shí)現(xiàn)代碼

    el-select 點(diǎn)擊按鈕滾動(dòng)到選擇框頂部的實(shí)現(xiàn)代碼

    本文通過實(shí)例代碼給大家分享el-select 點(diǎn)擊按鈕滾動(dòng)到選擇框頂部效果,主要代碼是在visibleChange在這個(gè)popper里面找到.el-select-dropdown__list,感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • Vue打包后訪問靜態(tài)資源路徑問題

    Vue打包后訪問靜態(tài)資源路徑問題

    在本篇文章里小編給各位整理的是關(guān)于Vue打包后訪問靜態(tài)資源路徑問題相關(guān)知識(shí)點(diǎn),需要的朋友們學(xué)習(xí)下。
    2019-11-11
  • 淺析webpack-bundle-analyzer在vue-cli3中的使用

    淺析webpack-bundle-analyzer在vue-cli3中的使用

    這篇文章主要介紹了webpack-bundle-analyzer在vue-cli3中的使用,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-10-10
  • Vue實(shí)現(xiàn)倒計(jì)時(shí)小功能

    Vue實(shí)現(xiàn)倒計(jì)時(shí)小功能

    這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)倒計(jì)時(shí)小功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09

最新評(píng)論

靖西县| 滨海县| 前郭尔| 镇远县| 临漳县| 彩票| 额济纳旗| 雅江县| 都江堰市| 腾冲县| 宁德市| 高陵县| 浠水县| 佛山市| 雷山县| 怀来县| 仪陇县| 台州市| 东光县| 芜湖市| 故城县| 革吉县| 彰化市| 高淳县| 余庆县| 饶河县| 濮阳县| 阳东县| 义乌市| 苗栗市| 宁强县| 揭东县| 乌拉特中旗| 平陆县| 资溪县| 岳阳市| 杂多县| 宁陵县| 桓仁| 井研县| 阿瓦提县|