props / emit
原理
父组件通过 props 向子组件传递数据,子组件通过 emit 发送事件给父组件。
应用场景
适用于父子组件之间的简单通信,父组件向子组件传递数据,子组件通过事件触发通知父组件。
示例代码
父组件:
<template>
<div>
<!-- 子组件 -->
<ChildComponent @notify="handleNotify"></ChildComponent>
</div>
</template>
<script>
import { defineComponent } from "vue";
import ChildComponent from './ChildComponent.vue';
export default defineComponent({
name: "父组件名",
components: {
ChildComponent
},
setup() {
const state = reactive({});
const handleNotify = (message) => {
console.log('从子组件接收到:', message);
}
return {
...toRefs(state),
handleNotify,
};
},
});
</script>
子组件:
<template>
<div>
<p>{{ message }}</p>
<button @click="notifyParent">通知父组件</button>
</div>
</template>
<script>
import { defineComponent } from "vue";
export default defineComponent({
name: "子组件名",
props: {
message: {
type: String,
default: "",
},
},
setup(props, { emit }) {
const state = reactive({});
const notifyParent = () => {
// 在父组件调用 notify 方法获取传的值
emit("notify", "子组件发送的消息" + props.message);
};
return {
...toRefs(state),
notifyParent,
};
},
});
</script>
Event Bus
事件总线(全局Vue实例)
原理
Vue 实例作为中央事件总线,通过 $on 监听事件,$emit 发布事件,实现任意组件间的通信。
应用场景
适用于跨越多层级关系的非父子组件通信,或者兄弟组件之间的通信。
示例代码
// main.js 或其他中心位置
import { createApp } from 'vue';
import App from './App.vue';
export const app = createApp(App);
export const eventBus = app.config.globalProperties.$eventBus = new app.config.globalProperties.Vue();
// 组件A 传递
eventBus.$emit('event-name', data);
// 组件B 接收
eventBus.$on('event-name', data => {
// 处理事件数据
});
Vuex
原理
Vue.js 的官方状态管理库,集中式存储管理应用的所有组件的状态。
应用场景
适用于大型单页应用中,多个组件需要共享状态或需要对状态进行复杂的管理操作。
示例代码
Vuex 状态管理:
// store/index.js
import { createStore } from 'vuex';
export default createStore({
state() {
return {
count: 0
};
},
mutations: {
increment(state) {
state.count++;
}
},
actions: {
incrementAsync({ commit }) {
setTimeout(() => {
commit('increment');
}, 1000);
}
},
getters: {
getCount: state => state.count
}
});
在组件中使用 Vuex:
<template>
<div>
<p>计数:{{ count }}</p>
<button @click="increment">增加</button>
</div>
</template>
<script>
import { defineComponent, computed } from "vue";
import { useStore } from "vuex";
export default defineComponent({
setup() {
const store = useStore();
const count = computed(() => store.state.count);
const increment = () => {
store.commit("increment");
};
return {
count,
increment,
};
},
});
</script>
Provide / Inject
原理
祖先组件通过 provide
提供数据,后代组件通过 inject
注入数据,实现祖先与后代之间的跨层级通信。
应用场景
适用于复杂的组件结构,需要在多层嵌套的组件中传递数据。
示例代码
祖先组件传递数据:
<script>
import { defineComponent, provide } from "vue";
export default defineComponent({
setup() {
provide('theme', 'dark');
},
});
</script>
后代组件接收数据:
<template>
<div>
<p>主题:{{ theme }}</p>
</div>
</template>
<script>
import { defineComponent, inject } from "vue";
export default defineComponent({
setup() {
const theme = inject('theme');
return { theme };
},
});
</script>
$attrs / $listeners
原理
子组件可以通过 $attrs
获取父组件传递的非 prop 特性,通过 $listeners
获取父组件传递的事件监听器。
应用场景
适用于需要在子组件中访问父组件的特性和监听器的场景。
示例代码
父组件:
<template>
<div>
<ChildComponent v-bind="$attrs" v-on="$listeners"></ChildComponent>
</div>
</template>
子组件:
<template>
<div>
<input type="text" v-bind="$attrs" v-on="$listeners">
<button @click="$emit('click')">点击</button>
</div>
</template>