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

Vue2實(shí)現(xiàn)組件通訊的常用方式

 更新時(shí)間:2026年04月15日 09:07:18   作者:霍理迪  
在 Vue 項(xiàng)目開發(fā)中,組件通訊是基礎(chǔ)也是核心,不同的組件關(guān)系(父子、祖先后代、任意組件)有著不同的最優(yōu)解方案,本文介紹了Vue項(xiàng)目中組件通訊的不同方式,包括父子組件的props、v-model和自定義事件,需要的朋友可以參考下

前言:

在 Vue 項(xiàng)目開發(fā)中,組件通訊是基礎(chǔ)也是核心。不同的組件關(guān)系(父子、祖先后代、任意組件)有著不同的最優(yōu)解方案。

一、父子通訊

誰(shuí)在模板中引入了另一個(gè)組件,誰(shuí)就是父組件,被引用的就是子組件。父子組件的通訊是最為頻繁的場(chǎng)景。

1、props 配置項(xiàng)

props主要用于讓子組件接收外部(父組件)傳過來的數(shù)據(jù)。它可以實(shí)現(xiàn)“父?jìng)髯?rdquo;,也可以通過傳遞函數(shù)實(shí)現(xiàn)“子傳父”

代碼實(shí)現(xiàn):

父?jìng)髯?/strong>:父組件在子組件標(biāo)簽上通過v-bind即:綁定動(dòng)態(tài)數(shù)據(jù)。

子傳父:父組件先定義一個(gè)帶形參的方法,并將該方法通過屬性傳給子組件;子組件在合適的時(shí)機(jī)調(diào)用該方法,將自身數(shù)據(jù)作為實(shí)參傳入

// 父組件 App.vue
<template>
  <div>
    <!-- 傳遞屬性 money 和 方法 getSonMsg -->
    <Girl :money="money" :getSonMsg="getSonMsg"/>
  </div>
</template>
<script>
import Girl from '@/components/Girl';
export default {
  components: { Girl },
  data() {
    return { money: { num: 1000 } }
  },
  methods: {
    getSonMsg(msg) {
      console.log('接收到了girl組件傳遞的數(shù)據(jù)', msg); // 父組件在這里接收到了子組件的數(shù)據(jù)
    }
  }
}
</script>
// 子組件 Girl.vue
<script>
export default {
  // 推薦使用對(duì)象方式接收,可限制類型、必要性及默認(rèn)值
  props: {
    money: { type: Object, required: true },
    getSonMsg: { type: Function }
  },
  data() { return { girlInfo: '我是girl組件' } },
  methods: {
    sendInfo() {
      // 觸發(fā)父組件傳來的方法,并傳入子組件的數(shù)據(jù)實(shí)現(xiàn)子傳父
      this.getSonMsg(this.girlInfo);
    }
  }
}
</script>

注意事項(xiàng): props 是只讀的,Vue 底層會(huì)監(jiān)視你對(duì) props 的修改,如果強(qiáng)行修改會(huì)發(fā)出警告。若業(yè)務(wù)需要,請(qǐng)將 props 的內(nèi)容復(fù)制一份到子組件的 data 中再進(jìn)行修改。另外,對(duì)于傳遞的復(fù)雜數(shù)據(jù)類型(如對(duì)象),Vue 無法監(jiān)測(cè)到內(nèi)部屬性內(nèi)容的改變,除非修改了地址值。

2、組件自定義事件

適用于子組件向父組件傳遞數(shù)據(jù)。核心邏輯是:誰(shuí)綁定,誰(shuí)觸發(fā)。父組件給子組件綁定自定義事件,子組件內(nèi)部觸發(fā)該事件

代碼實(shí)現(xiàn)與兩種綁定方式:

方式一:標(biāo)簽上直接綁定 父組件使用 @事件名="回調(diào)函數(shù)" 綁定

// 父組件
<HelloWorld @event2="handleEvent"></HelloWorld>

// 子組件 HelloWorld.vue
methods: {
  doSome() {
    // 觸發(fā) event2 事件,并可以傳遞多個(gè)參數(shù)
    this.$emit('event2', this.msg, 666, 8888); 
  }
}

方式二:代碼動(dòng)態(tài)綁定 (使用 ref) 如果想要更靈活的綁定時(shí)機(jī),可以使用 ref。注意:不能在 created 鉤子中綁定(此時(shí) DOM 未渲染),通常在 mounted 中綁定

// 父組件
<template>
  <HelloWorld ref="hello" />
</template>
<script>
export default {
  mounted() {
    // 使用箭頭函數(shù),確保 this 指向父組件實(shí)例
    this.$refs.hello.$on('event2', (msg) => {
      console.log('收到數(shù)據(jù)', msg, this); 
    });
  }
}
</script>

注意事項(xiàng):

this 指向:如果使用代碼綁定(方式二),回調(diào)函數(shù)一定要寫成箭頭函數(shù)或者配置在父組件的 methods 中。如果寫成普通匿名函數(shù) function() {},此時(shí)的 this 會(huì)指向觸發(fā)事件的子組件(HelloWorld),而不是父組件。

原生事件與解綁:如果要在組件標(biāo)簽上綁定原生的 DOM 事件(如 click),必須加上 .native 修飾符,否則 Vue 會(huì)將其視為自定義事件。組件銷毀前,建議使用 this.\$off('事件名') 或 this.\$off() 解綁事件,防止內(nèi)存泄漏

3、ref /  \$parent /  \$children

ref:使用在普通 HTML 標(biāo)簽上獲取的是 DOM 元素;使用在組件標(biāo)簽上獲取的是該子組件實(shí)例,可以借此直接調(diào)用子組件的數(shù)據(jù)和方法,如this.\$refs.hello.name

 \$parent /  \$childre

子組件通過this.parent.屬性即可訪問父組件;父組件也可以通過this.\$children訪問子組件實(shí)例。

這三者都會(huì)增加組件的強(qiáng)耦合,通常僅作為一種捷徑通信。

二、任意組件通訊

1、 全局事件總線 ($bus)

全局事件總線適用于任何關(guān)系的組件通信(尤其是兄弟組件)。它的原理是給項(xiàng)目中所有的組件找一個(gè)共享的對(duì)象(必須具備 \$on、\$emit、\$off 方法),所有組件都通過它來收發(fā)數(shù)據(jù)。

配置總線的兩種底層方式(明確 vc 與 vm): 要?jiǎng)?chuàng)建一個(gè)所有組件都能訪問的對(duì)象,我們可以利用原型鏈。Vue 的組件實(shí)例(vc - VueComponent)和 Vue 實(shí)例(vm - Vue)都繼承自 Vue 原型。

方式一:創(chuàng)建一個(gè)共享的 vc 對(duì)象

Vue 底層解析組件標(biāo)簽時(shí)會(huì) new VueComponent(),我們可以手動(dòng)創(chuàng)建一個(gè)實(shí)例來作為總線。

// 在 main.js 中
// 1. 獲取 VueComponent 構(gòu)造函數(shù)
const VueComponentConstructor = Vue.extend({});
// 2. 實(shí)例化一個(gè) vc 對(duì)象
const globelvc = new VueComponentConstructor();
// 3. 將其掛載到 Vue 原型上
Vue.prototype.$bus = globelvc; 

方式二:直接使用 vm 對(duì)象(推薦寫法)

在 main.js 創(chuàng)建 Vue 根實(shí)例時(shí),在 beforeCreate 鉤子中將當(dāng)前的 this(也就是 vm 實(shí)例自身)掛載到原型上。

// 在 main.js 中
new Vue({
  render: (h) => h(App),
  beforeCreate() {
    // 安裝全局事件總線,$bus 就是當(dāng)前應(yīng)用的 vm
    Vue.prototype.$bus = this; 
  }
}).$mount("#app");

使用規(guī)范: 永遠(yuǎn)記?。篈 組件向 B 組件傳數(shù)據(jù),應(yīng)該在 B 組件中綁定事件(接),在 A 組件中觸發(fā)事件(傳)

接收方 (B 組件):mounted() { this.\$bus.\$on('receiveMsg', (msg) => { ... }) }

發(fā)送方 (A 組件)this.\$bus.\$emit('receiveMsg', 數(shù)據(jù))

注意:養(yǎng)成好習(xí)慣,接收方組件被銷毀前,必須在 beforeDestroy 中調(diào)用 this.\$bus.\$off('receiveMsg') 解綁事件

2、消息訂閱與發(fā)布 (pubsub-js)

借助第三方庫(kù)實(shí)現(xiàn),適用于任意前端框架。安裝 npm i pubsub-js 后,引入 pubsub 對(duì)象。接收方使用 pubsub.subscribe('消息名', 回調(diào)) 訂閱,發(fā)送方使用 pubsub.publish('消息名', 數(shù)據(jù)) 發(fā)布

三、Vuex 集中式狀態(tài)管理

當(dāng)多個(gè)組件依賴于同一狀態(tài),或來自不同組件的行為需要變更同一狀態(tài)時(shí),就必須使用 Vuex。 全局事件總線的關(guān)注點(diǎn)在于“數(shù)據(jù)傳來傳去”,并沒有讓數(shù)據(jù)真正共享;而 Vuex 的關(guān)注點(diǎn)在于“數(shù)據(jù)本身就在 Vuex 上共享”,任何組件修改它,其他組件都會(huì)同步更新

1. Vuex 的核心五大屬性

Vuex 包含五個(gè)核心屬性:State、Getters、Mutations、Actions、Modules。

State:存儲(chǔ) Vuex 的基本數(shù)據(jù)(變量)。

Getters:基于 State 的派生數(shù)據(jù),邏輯復(fù)雜且復(fù)用性高時(shí)使用,相當(dāng)于 State 的計(jì)算屬性。

Mutations:提交更新數(shù)據(jù)的唯一途徑且必須是同步的。包含事件類型和回調(diào)函數(shù),回調(diào)接收 state 和傳入的值作為參數(shù),使用 this.\$store.commit() 觸發(fā)。

Actions:處理復(fù)雜的業(yè)務(wù)邏輯或包含任意異步操作(如發(fā)送 ajax 請(qǐng)求)。Action 拿到結(jié)果后提交給 Mutation 進(jìn)行狀態(tài)變更,而不是直接修改 State。使用 this.\$store.dispatch() 觸發(fā)。

Modules:如果將所有狀態(tài)集中在一棵樹上會(huì)非常臃腫。Modules 允許將 Store 分割成包含自己 State、Mutations、Actions 的多個(gè)模塊,方便管理。

實(shí)現(xiàn):我們將這四個(gè)屬性集中在 Vuex 的核心對(duì)象配置中(通常在 store/index.js 或類似文件中)

import Vue from "vue";
import Vuex from "vuex";
import axios from "axios"; // 引入網(wǎng)絡(luò)請(qǐng)求庫(kù)

Vue.use(Vuex);

// 1. State:定義全局共享的數(shù)據(jù)
const state = {
  username: "zhangsan", // 基礎(chǔ)字符串狀態(tài)
  studentName: [
    { id: "001", name: "孫悟空" },
    { id: "002", name: "豬八戒" }
  ],
  userList: [] // 準(zhǔn)備存放異步請(qǐng)求來的列表數(shù)據(jù)
};

// 2. Getters:基于 State 加工的計(jì)算屬性
const getters = {
  // 每一個(gè) getter 方法會(huì)自動(dòng)接收 state 作為第一個(gè)參數(shù)
  // 需求:將 username 反轉(zhuǎn)展示
  reverseName(state) {
    return state.username.split("").reverse().join("");
  }
};

// 3. Mutations:負(fù)責(zé)同步更新 State 的方法
const mutations = {
  // 接收 state 作為第一個(gè)參數(shù),value(提交的載荷)作為第二個(gè)參數(shù)
  SAVE_STUDENT(state, value) {
    // 只能在此進(jìn)行同步操作直接修改 state
    state.studentName.unshift({ id: Date.now(), name: value });
  },
  
  // 用于接收異步操作拿回來的數(shù)據(jù)并賦值給 state
  GET_USER_INFO(state, value) {
    state.userList = value;
  }
};

// 4. Actions:處理異步操作和復(fù)雜邏輯
const actions = {
  // context 相當(dāng)于一個(gè)迷你的 store 對(duì)象,包含 commit、dispatch 等方法
  
  // 示例 A:簡(jiǎn)單的封裝,將外部傳來的值交給 Mutation
  saveStudent(context, value) {
    // 可以在這里做一些邏輯判斷,判斷通過后再提交
    context.commit("SAVE_STUDENT", value);
  },

  // 示例 B:真實(shí)的異步 Ajax 請(qǐng)求
  async getUserInfo(context) {
    try {
      // 模擬發(fā)送異步網(wǎng)絡(luò)請(qǐng)求獲取數(shù)據(jù)
      let res = await axios.get("api/user"); 
      // 拿到數(shù)據(jù)后,提交給 Mutations 去更新 State
      context.commit("GET_USER_INFO", res.data); 
    } catch (error) {
      console.log(error.message);
    }
  }
};

// 創(chuàng)建并暴露 store 對(duì)象
export default new Vuex.Store({
  state,
  getters,
  mutations,
  actions,
});

2. Vuex 模塊化開發(fā)與 map 輔助函數(shù)

在大型項(xiàng)目中,模塊化開發(fā)是必選項(xiàng)。開啟命名空間 namespaced: true 可以讓各個(gè)模塊的狀態(tài)內(nèi)聚。 同時(shí),使用 mapState, mapGetters, mapActions, mapMutations 能夠大幅簡(jiǎn)化組件內(nèi)部調(diào)用 store 的代碼。

模塊化與輔助函數(shù)代碼實(shí)踐:

// store/student.js (學(xué)生模塊)
export default {
  namespaced: true, // 開啟命名空間
  state: { studentNum: 5, studentName: "張三" },
  getters: {
    reverseStudentName(state) { return state.studentName.split("").reverse().join(""); }
  },
  mutations: {
    STU_NUM_FUN(state, value) { state.studentNum += value; }
  },
  actions: {
    stuNumFun(context, value) { context.commit("STU_NUM_FUN", value); }
  }
};

// store/index.js (主文件)
import Vue from "vue";
import Vuex from "vuex";
import student from "./student";
Vue.use(Vuex);
export default new Vuex.Store({
  modules: { student } // 注冊(cè)模塊
});

在組件中使用輔助函數(shù)映射:

// 組件內(nèi)
import { mapState, mapGetters, mapActions } from 'vuex';

export default {
  computed: {
    // 數(shù)組形式或?qū)ο笮问接成淠K內(nèi)的 state 和 getters
    ...mapState('student', ['studentNum', 'studentName']),
    ...mapGetters('student', ['reverseStudentName'])
  },
  methods: {
    // 映射 actions,模板中調(diào)用時(shí)直接傳參 @click="stuNumFun(2)"
    ...mapActions('student', ['stuNumFun'])
  }
}

3. Action 中的異步請(qǐng)求

如果 ajax 請(qǐng)求來的數(shù)據(jù)需要被多個(gè)組件共享復(fù)用,應(yīng)該將請(qǐng)求邏輯封裝在 Vuex 的 Action 里,并包裝成 Promise。

// test.js 模塊
import axios from "axios";
export default {
  namespaced: true,
  state: { list: [] },
  mutations: { GET_USER_INFO(state, value) { state.list = value; } },
  actions: {
    async getUserInfo(context) {
      try {
        let res = await axios.get("api/user");
        context.commit("GET_USER_INFO", res.data); // 請(qǐng)求成功后提交 mutation
      } catch (error) { console.log(error.message); }
    }
  }
}

4. Vuex 數(shù)據(jù)刷新丟失問題與持久化

痛點(diǎn):F5 刷新頁(yè)面時(shí),Vue 實(shí)例會(huì)被銷毀重建,Vuex 寫在內(nèi)存中的 state 數(shù)據(jù)會(huì)重新初始化,導(dǎo)致登錄 token 等數(shù)據(jù)丟失。 解決方案:引入 vuex-persistedstate 插件進(jìn)行數(shù)據(jù)持久化,它會(huì)自動(dòng)將數(shù)據(jù)同步到 localStorage 中。

// 安裝: npm install vuex-persistedstate
// store/index.js
import createPersistedState from 'vuex-persistedstate'

export const store = new Vuex.Store({
  modules: { student },
  plugins: [
    createPersistedState({
      // 可選配置:指定需要持久化的模塊數(shù)據(jù)
      reducer(val) {
        return { student: val.student } 
      }
    })
  ]
})

四、其他通訊方式

1. \$attrs 與 \$listeners (爺孫透?jìng)?

用于祖先組件向深層后代組件傳遞數(shù)據(jù),解決中間組件僅起到橋梁作用的問題。

\$attrs 包含了祖先傳遞但在當(dāng)前組件 props 中未聲明的屬性。在中間組件設(shè)置 inheritAttrs: false 阻止屬性自動(dòng)綁定到根元素,然后通過 v-bind="$attrs" 將其向下透?jìng)鳌?/p>

\$listeners 包含祖先傳遞的所有事件監(jiān)聽器,通過 v-on="$listeners" 向下傳遞,孫組件即可直接觸發(fā)爺爺組件的事件

2. Provide 與 Inject (依賴注入)

同樣用于祖先向后代傳遞。祖先組件通過 provide() 返回提供的數(shù)據(jù),后代通過 inject: ['屬性名'] 接收。 注意:這主要用于單向傳遞。如果祖先傳遞的是基礎(chǔ)類型,后代修改它會(huì)報(bào)錯(cuò);如果是復(fù)雜引用類型,修改雖不報(bào)錯(cuò)但會(huì)失去響應(yīng)式,破壞單向數(shù)據(jù)流結(jié)構(gòu),增加代碼維護(hù)難度。

3. v-model 通信

在自定義組件上,v-model 本質(zhì)上是 :value 和 @input 事件的語(yǔ)法糖,用于實(shí)現(xiàn)極其方便的父子雙向綁定。父組件直接 <Child v-model="data"/>,子組件接收 props: ['value'],數(shù)據(jù)變化時(shí)

this.$ emit('input', 新值) 即可實(shí)現(xiàn)同步修改源數(shù)據(jù)。

4. 插槽 Slots (結(jié)構(gòu)傳遞)

插槽讓父組件可以向子組件指定位置插入完整的 HTML 結(jié)構(gòu)。

默認(rèn)/具名插槽:父組件向子組件分發(fā)結(jié)構(gòu)。

作用域插槽(子傳父的變體):數(shù)據(jù)在子組件自身,但根據(jù)數(shù)據(jù)生成的 HTML 結(jié)構(gòu)由父組件決定。子組件通過 <slot :自定義名="數(shù)據(jù)"> 傳出數(shù)據(jù),父組件用 <template scope="接收名"> 拿到數(shù)據(jù)并構(gòu)建 UI。

總覽

組件關(guān)系傳遞方式
父?jìng)髯?/td>props,v-model,默認(rèn)插槽,具名插槽, \$parent
子傳父props,自定義事件,v-model, \$refs, \$children,作用域插槽
祖先與后代 \$attrs / \$listeners ,provide / inject
任意組件通訊 \$bus,pubsub,vuex

以上就是Vue2實(shí)現(xiàn)組件通訊的常用方式的詳細(xì)內(nèi)容,更多關(guān)于Vue2組件通訊方式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue-router?導(dǎo)航完成后獲取數(shù)據(jù)的實(shí)現(xiàn)方法

    vue-router?導(dǎo)航完成后獲取數(shù)據(jù)的實(shí)現(xiàn)方法

    這篇文章主要介紹了vue-router?導(dǎo)航完成后獲取數(shù)據(jù),通過使用生命周期的 created() 函數(shù),在組件創(chuàng)建完成后調(diào)用該方法,本文結(jié)合實(shí)例代碼給大家講解的非常詳細(xì)需要的朋友可以參考下
    2022-11-11
  • 使用Vue3和ApexCharts實(shí)現(xiàn)交互式3D折線圖

    使用Vue3和ApexCharts實(shí)現(xiàn)交互式3D折線圖

    ApexCharts 是一個(gè)功能強(qiáng)大的 JavaScript 庫(kù),用于創(chuàng)建交互式、可定制的圖表,在 Vue.js 中,它可以通過 vue3-apexcharts 插件輕松集成,本文給大家介紹了使用Vue3和ApexCharts實(shí)現(xiàn)交互式3D折線圖,需要的朋友可以參考下
    2024-06-06
  • Vue項(xiàng)目之學(xué)生管理系統(tǒng)實(shí)例詳解

    Vue項(xiàng)目之學(xué)生管理系統(tǒng)實(shí)例詳解

    這篇文章主要為大家詳細(xì)介紹了Vue項(xiàng)目之學(xué)生管理系統(tǒng)實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • vue3?ts編寫echart是tooltip無法展示的解決

    vue3?ts編寫echart是tooltip無法展示的解決

    這篇文章主要介紹了vue3?ts編寫echart是tooltip無法展示的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • Vue中watchEffect的追蹤邏輯介紹

    Vue中watchEffect的追蹤邏輯介紹

    這篇文章主要介紹了Vue中watchEffect的追蹤邏輯,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • 詳解vue配置后臺(tái)接口方式

    詳解vue配置后臺(tái)接口方式

    這篇文章主要介紹了vue配置后臺(tái)接口方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • Vue Router路由守衛(wèi)超詳細(xì)介紹

    Vue Router路由守衛(wèi)超詳細(xì)介紹

    路由守衛(wèi),簡(jiǎn)單理解來說就是,當(dāng)用戶要進(jìn)行一些操作時(shí),我需要用戶的一些信息或數(shù)據(jù)或行為,我判斷過后,才會(huì)同意用戶進(jìn)行操作,說到這里,我想大家心里都或多或少有點(diǎn)理解了吧
    2023-01-01
  • Vue簡(jiǎn)易注冊(cè)頁(yè)面+發(fā)送驗(yàn)證碼功能的實(shí)現(xiàn)示例

    Vue簡(jiǎn)易注冊(cè)頁(yè)面+發(fā)送驗(yàn)證碼功能的實(shí)現(xiàn)示例

    本文主要介紹了Vue簡(jiǎn)易注冊(cè)頁(yè)面+發(fā)送驗(yàn)證碼功能的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Vue3中Composition的API用法詳解

    Vue3中Composition的API用法詳解

    這篇文章主要為大家詳細(xì)介紹了Vue3中Composition的一些常見API的用法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-06-06
  • vue?select組件綁定的值為數(shù)字類型遇到的問題

    vue?select組件綁定的值為數(shù)字類型遇到的問題

    這篇文章主要介紹了vue?select組件綁定的值為數(shù)字類型遇到的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09

最新評(píng)論

福清市| 阳高县| 桐柏县| 房产| 仙游县| 彝良县| 乌拉特中旗| 武强县| 桂平市| 桃园县| 凤庆县| 镇江市| 调兵山市| 明水县| 甘谷县| 通海县| 娱乐| 祁连县| 筠连县| 昭觉县| 溆浦县| 拜城县| 麻城市| 三明市| 平舆县| 北京市| 渭源县| 泰和县| 巴林右旗| 和硕县| 兴和县| 修武县| 华坪县| 昌黎县| 灵寿县| 锡林郭勒盟| 安福县| 巴彦县| 顺昌县| 忻州市| 绩溪县|