在Vue.js中,父子组件通信是一个常见的需求。有五种主要的方法可以实现父子组件通信,分别是props、$emit、$refs、provide/inject和自定义事件。每种方法都有其各自的优缺点,在不同的场景下使用不同的方法可以实现更好的效果。
1. props
props是props(properties)的缩写,它是子组件从父组件接收数据的常用方法。父组件通过在子组件的template标签中声明props,子组件通过在data()方法中定义props来接收数据。
<!-- 父组件 -->
<template>
<child-component :message="message"></child-component>
</template>
<script>
export default {
data() {
return {
message: "Hello, world!"
}
}
}
</script>
<!-- 子组件 -->
<template>
<div>{{ message }}</div>
</template>
<script>
export default {
props: ["message"],
data() {
return {}
}
}
</script>
2. $emit
$emit是emit(触发)的缩写,它是子组件向父组件发送事件的常用方法。子组件通过调用$emit()方法来触发事件,父组件通过在子组件的template标签中声明@事件名来监听事件。
<!-- 父组件 -->
<template>
<child-component @message="handleMessage"></child-component>
</template>
<script>
export default {
methods: {
handleMessage(message) {
console.log(message)
}
}
}
</script>
<!-- 子组件 -->
<template>
<button @click="handleClick">点击我</button>
</template>
<script>
export default {
methods: {
handleClick() {
this.$emit("message", "Hello, world!")
}
}
}
</script>
3. $refs
$refs是refs(引用)的缩写,它是父组件访问子组件实例的常用方法。父组件通过在子组件的template标签中声明ref,子组件通过在data()方法中定义ref来暴露实例。
<!-- 父组件 -->
<template>
<child-component ref="child"></child-component>
</template>
<script>
export default {
mounted() {
console.log(this.$refs.child)
}
}
</script>
<!-- 子组件 -->
<template>
<div>我是子组件</div>
</template>
<script>
export default {
data() {
return {}
}
}
</script>
4. provide/inject
provide/inject是Vue.js 2.2.0引入的新特性,它是一种父子组件间通信方式。父组件通过provide()方法提供数据,子组件通过inject()方法注入数据。
<!-- 父组件 -->
<template>
<provide>
<child-component></child-component>
</provide>
</template>
<script>
export default {
provide() {
return {
message: "Hello, world!"
}
}
}
</script>
<!-- 子组件 -->
<template>
<div>{{ message }}</div>
</template>
<script>
export default {
inject: ["message"],
data() {
return {}
}
}
</script>
5. 自定义事件
自定义事件是通过dispatchEvent()方法触发,addEventListener()方法监听的事件。
<!-- 父组件 -->
<template>
<button @click="handleClick">点击我</button>
</template>
<script>
export default {
methods: {
handleClick() {
dispatchEvent(new CustomEvent("message", { detail: "Hello, world!" }))
}
}
}
</script>
<!-- 子组件 -->
<template>
<div>
<button @click="handleMessage">点击我</button>
<p id="message"></p>
</div>
</template>
<script>
export default {
methods: {
handleMessage() {
addEventListener("message", (event) => {
document.getElementById("message").innerText = event.detail
})
}
}
}
</script>
以上五种方法各有优缺点,在不同的场景下使用不同的方法可以实现更好的效果。