Vue组件间的通信详解

在Vue中,组件之间的通信可以有多种方式实现:

  1. Props 和 $emit

    • Props:父组件向子组件传递数据时,通过属性绑定(v-bind 或 :)将数据作为属性传给子组件。子组件需要在props选项中声明它接收的属性列表。
    • **emit∗∗:子组件向父组件发送事件和数据,通过‘emit**:子组件向父组件发送事件和数据,通过 `emit∗∗:子组件向父组件发送事件和数据,通过‘emit(eventName, payload)触发自定义事件,并附带数据。父组件可以在使用子组件的地方监听这个事件,通常通过v-on: eventName@eventName` 来实现。
  2. refs

    • refs:直接访问子组件实例或DOM元素。当需要获取子组件的状态或者调用其方法时,可以给子组件添加一个ref引用,在父组件中通过‘this.refs**:直接访问子组件实例或DOM元素。当需要获取子组件的状态或者调用其方法时,可以给子组件添加一个ref引用,在父组件中通过 `this.refs∗∗:直接访问子组件实例或DOM元素。当需要获取子组件的状态或者调用其方法时,可以给子组件添加一个ref引用,在父组件中通过‘this.refs.refName` 访问该子组件实例。
  3. Event Bus (全局事件总线)

    • 创建一个独立的 Vue 实例作为事件中心,通过它的 $on 和 $emit 方法来在任何组件之间发送和接收事件,以此实现跨级或兄弟组件间的通信。
  4. Vuex

    • Vuex 是 Vue 提供的状态管理库,用于管理整个应用层级的状态,允许组件间共享状态并通过 actions、mutations 进行状态的变更和同步。
  5. 依赖注入(provide / inject)

    • 父组件可以通过 provide 选项提供数据,而无需显式传递 props,然后在子孙组件中通过 inject 选项来注入并使用这些数据。
  6. 父子组件通信补充方式

    • 使用回调函数作为 Prop,父组件传递一个方法给子组件,子组件在适当的时候调用此方法以更新父组件的状态。
    • 使用 v-model 进行双向数据绑定(仅限于表单输入类组件或其他支持 v-model 的自定义组件)。
  7. 动态组件与 keep-alive 缓存

    • 动态组件配合 keep-alive 可以在切换组件时保留状态,并且可以通过激活/停用状态的改变进行间接通信。

Props 和 $emit 父组件

父组件

<template>
  <div>
    <child-component :message="parentMessage" @update-message="handleUpdateMessage"></child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: { ChildComponent },
  data() {
    return {
      parentMessage: 'Hello from parent'
    }
  },
  methods: {
    handleUpdateMessage(newMessage) {
      this.parentMessage = newMessage;
    }
  }
}
</script>

 子组件

<template>
  <div>
    {{ message }}
    <button @click="updateMessage">Update Message</button>
  </div>
</template>

<script>
export default {
  props: ['message'],
  methods: {
    updateMessage() {
      this.$emit('update-message', 'New message from child');
    }
  }
}
</script>

 refs

父组件

<template>
  <div>
    <child-component ref="childRef"></child-component>
    <button @click="callChildMethod">Call Child Method</button>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: { ChildComponent },
  methods: {
    callChildMethod() {
      this.$refs.childRef.childMethod();
    }
  }
}

  子组件

<script>
export default {
  methods: {
    childMethod() {
      console.log('Child method called');
    }
  }
}
</script>

 Event Bus

 

// eventBus.js
import Vue from 'vue';
export const EventBus = new Vue();

// 在任意组件内发送事件
EventBus.$emit('customEvent', payload);

// 在任意组件内接收事件
EventBus.$on('customEvent', (payload) => {
  console.log(payload);
});

Vuex 

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    sharedData: 'Global State'
  },
  mutations: {
    updateSharedData(state, newData) {
      state.sharedData = newData;
    }
  },
  actions: {
    updateData({ commit }, newData) {
      commit('updateSharedData', newData);
    }
  },
  getters: {
    getSharedData(state) {
      return state.sharedData;
    }
  }
});

 组件中使用

<script>
import { mapState, mapActions } from 'vuex';

export default {
  computed: {
    ...mapState(['sharedData'])
  },
  methods: {
    ...mapActions(['updateData'])
  },
  mounted() {
    this.updateData('Updated Global State');
    console.log(this.sharedData);
  }
};
</script>

provide / inject

父组件

<script>
provide() {
  return {
    parentData: 'Provided by Parent'
  };
}
</script>

 子组件

<script>
inject: ['parentData'],
created() {
  console.log(this.parentData); // "Provided by Parent"
}
</script>

 子向父传递

父组件

<template>
  <div>
    <child-component :notifyParent="updateParentData"></child-component>
    <p>Parent Data: {{ parentData }}</p>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: { ChildComponent },
  data() {
    return {
      parentData: ''
    }
  },
  methods: {
    updateParentData(newData) {
      this.parentData = newData;
    }
  }
}
</script>

子组件

<template>
  <button @click="callParentMethod">Update Parent Data</button>
</template>

<script>
export default {
  props: {
    notifyParent: { type: Function, required: true }
  },
  methods: {
    callParentMethod() {
      this.notifyParent('New data from child');
    }
  }
}
</script>

 v-model 进行双向数据绑定

 父组件

<template>
  <input-typeahead v-model="searchText" />
  <p>Search Text: {{ searchText }}</p>
</template>

<script>
import InputTypeahead from './InputTypeahead.vue'

export default {
  components: { InputTypeahead },
  data() {
    return {
      searchText: ''
    }
  }
}
</script>

子组件

<template>
  <input type="text" :value="value" @input="onInput" />
</template>

<script>
export default {
  model: {
    prop: 'value',
    event: 'input'
  },
  props: {
    value: String
  },
  methods: {
    onInput(event) {
      this.$emit('input', event.target.value);
    }
  }
}
</script>

动态组件与 keep-alive 缓存进行间接通信

<template>
  <div>
    <button @click="currentTab = 'tab1'">Tab 1</button>
    <button @click="currentTab = 'tab2'">Tab 2</button>
    
    <keep-alive>
      <component :is="currentTab === 'tab1' ? Tab1 : Tab2" @change-data="handleDataChange" />
    </keep-alive>
  </div>
</template>

<script>
import Tab1 from './Tab1.vue';
import Tab2 from './Tab2.vue';

export default {
  components: { Tab1, Tab2 },
  data() {
    return {
      currentTab: 'tab1',
      sharedData: {}
    }
  },
  methods: {
    handleDataChange(data) {
      this.sharedData = data;
    }
  }
}
</script>

其中,Tab1 和 Tab2 组件可以通过 $emit 触发 change-data 事件来更新父组件的状态。当切换回已缓存的组件时,由于状态被 keep-alive 保留,可以继续显示上次离开时的数据或状态。

  • 22
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Vue 3 提供了多种组件通信的方法,包括 Props、事件、Provide/Inject、$attrs/$listeners、Ref、Custom Events 等。下面我会逐一详细介绍这些方法。 1. Props:通过向子组件传递属性值来实现父子组件通信。父组件可以通过 props 属性将数据传递给子组件,并在子组件中使用。子组件通过 props 接收父组件传递的数据,并进行相应的处理。 2. 事件:父组件可以通过自定义事件的方式向子组件传递数据。子组件通过 $emit 方法触发事件,并将数据作为参数传递给父组件。父组件通过在子组件上监听自定义事件,并在事件处理函数中接收子组件传递的数据。 3. Provide/Inject:父组件可以通过 provide 方法提供数据,然后在子组件中通过 inject 方法注入数据。这种方式可以实现跨层级的组件通信,但是不推荐在大型项目中过度使用。 4. $attrs/$listeners:$attrs 用于获取父组件传递给子组件的非 prop 属性,$listeners 用于获取父组件传递给子组件的事件。这两个属性可以使得子组件可以接收父组件的所有属性和事件,从而简化了父子组件通信。 5. Ref:Ref 是一个特殊的对象,可以被用于在组件共享可变的状态。通过 ref 函数创建一个 ref 对象,并将其传递给子组件。子组件可以通过 .value 来访问和修改 ref 对象的值。 6. Custom Events:在 Vue 3 中,自定义事件可以通过创建一个新的事件实例,并使用 $on 和 $emit 方法进行监听和触发。这种方法可以实现更灵活的组件通信方式。 以上就是一些 Vue 3 中常用的组件通信方法。根据具体的场景和需求,选择合适的方法来实现组件通信。希望能对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mars空港

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值