欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 明星 > Vue 3 组件通信教程

Vue 3 组件通信教程

2025/5/7 6:52:42 来源:https://blog.csdn.net/wscfan/article/details/144024327  浏览:    关键词:Vue 3 组件通信教程

Vue 3 组件通信教程

1. Props 父传子

1.1 基础用法

在 Vue 3 中,我们使用 defineProps 来声明组件的 props:

<!-- 子组件 ChildComponent.vue -->
<script setup>
const props = defineProps({message: String,count: {type: Number,required: true,default: 0},items: {type: Array,default: () => []}
})
</script><template><div><p>{{ message }}</p><p>Count: {{ count }}</p></div>
</template>

父组件中使用:

<!-- 父组件 ParentComponent.vue -->
<script setup>
import { ref } from 'vue'
import ChildComponent from './ChildComponent.vue'const parentMessage = ref('Hello from parent')
const parentCount = ref(42)
</script><template><ChildComponent :message="parentMessage":count="parentCount"/>
</template>

1.2 Props 验证

Props 可以设置详细的验证规则:

<script setup>
const props = defineProps({// 基础类型检查propA: Number,// 多种类型propB: [String, Number],// 必填字段propC: {type: String,required: true},// 带有默认值propD: {type: Number,default: 100},// 带有默认值的对象propE: {type: Object,default: () => ({ message: 'hello' })},// 自定义验证函数propF: {validator(value) {return ['success', 'warning', 'danger'].includes(value)}}
})
</script>

2. Emits 子传父

2.1 基础用法

使用 defineEmits 声明事件:

<!-- 子组件 ChildComponent.vue -->
<script setup>
const emit = defineEmits(['update', 'delete'])const handleClick = () => {emit('update', { id: 1, data: 'new value' })
}
</script><template><button @click="handleClick">更新数据</button>
</template>

父组件中接收事件:

<!-- 父组件 ParentComponent.vue -->
<script setup>
import ChildComponent from './ChildComponent.vue'const handleUpdate = (payload) => {console.log('收到更新:', payload)
}
</script><template><ChildComponent @update="handleUpdate" />
</template>

2.2 带验证的 Emits

<script setup>
const emit = defineEmits({// 不带验证函数click: null,// 带验证函数submit: (payload) => {if (!payload.email) {return false}return true}
})
</script>

3. v-model 双向绑定

3.1 基础用法

<!-- 子组件 CustomInput.vue -->
<script setup>
defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script><template><input:value="modelValue"@input="emit('update:modelValue', $event.target.value)"/>
</template>

父组件中使用:

<script setup>
import { ref } from 'vue'
import CustomInput from './CustomInput.vue'const text = ref('')
</script><template><CustomInput v-model="text" /><p>输入的内容:{{ text }}</p>
</template>

3.2 多个 v-model 绑定

<!-- 子组件 UserForm.vue -->
<script setup>
defineProps(['firstName', 'lastName'])
const emit = defineEmits(['update:firstName', 'update:lastName'])
</script><template><input:value="firstName"@input="emit('update:firstName', $event.target.value)"/><input:value="lastName"@input="emit('update:lastName', $event.target.value)"/>
</template>

父组件使用:

<script setup>
import { ref } from 'vue'
import UserForm from './UserForm.vue'const firstName = ref('')
const lastName = ref('')
</script><template><UserFormv-model:firstName="firstName"v-model:lastName="lastName"/>
</template>

4. provide/inject 依赖注入

4.1 基础用法

<!-- 父组件提供数据 -->
<script setup>
import { provide, ref } from 'vue'const theme = ref('dark')
provide('theme', theme)
</script><!-- 子组件注入数据 -->
<script setup>
import { inject } from 'vue'const theme = inject('theme', 'light') // 第二个参数是默认值
</script>

4.2 响应式数据注入

<!-- 父组件 -->
<script setup>
import { provide, ref, readonly } from 'vue'const count = ref(0)
const incrementCount = () => {count.value++
}// 提供只读值和修改方法
provide('count', readonly(count))
provide('increment', incrementCount)
</script><!-- 子组件 -->
<script setup>
import { inject } from 'vue'const count = inject('count')
const increment = inject('increment')
</script><template><button @click="increment">{{ count }}</button>
</template>

5. EventBus 事件总线

虽然 Vue 3 移除了内置的事件总线,但我们可以使用第三方库或自己实现一个简单的事件总线:

// eventBus.js
import mitt from 'mitt'
export default mitt()

使用示例:

<!-- 组件 A -->
<script setup>
import eventBus from './eventBus'const sendMessage = () => {eventBus.emit('custom-event', { message: 'Hello!' })
}
</script><!-- 组件 B -->
<script setup>
import { onMounted, onUnmounted } from 'vue'
import eventBus from './eventBus'const handleEvent = (data) => {console.log(data.message)
}onMounted(() => {eventBus.on('custom-event', handleEvent)
})onUnmounted(() => {eventBus.off('custom-event', handleEvent)
})
</script>

6. refs 直接访问

6.1 模板引用

<!-- 父组件 -->
<script setup>
import { ref, onMounted } from 'vue'
import ChildComponent from './ChildComponent.vue'const childRef = ref(null)onMounted(() => {// 访问子组件的方法或属性childRef.value.someMethod()
})
</script><template><ChildComponent ref="childRef" />
</template><!-- 子组件 -->
<script setup>
// 需要显式暴露方法给父组件
defineExpose({someMethod() {console.log('方法被调用')}
})
</script>

最佳实践建议

  1. 优先使用 props 和 emits 进行父子组件通信
  2. 对于跨多层组件的通信,考虑使用 provide/inject
  3. 对于全局状态管理,使用 Vuex 或 Pinia
  4. 避免过度使用 EventBus,它可能导致维护困难
  5. 谨慎使用 refs 直接访问子组件,这可能破坏组件封装性

注意事项

  1. Props 是只读的,不要在子组件中直接修改
  2. 使用 v-model 时注意命名冲突
  3. provide/inject 的响应式数据建议使用 readonly 包装
  4. 在组件卸载时记得清理事件监听器
  5. 使用 TypeScript 时,建议为 props 和 emits 添加类型声明

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词