Vue 3 组件通信教程

devtools/2024/11/28 21:49:35/

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 添加类型声明

http://www.ppmy.cn/devtools/137761.html

相关文章

部署实战(二)--修改jar中的文件并重新打包成jar文件

一.jar文件 JAR 文件就是 Java Archive &#xff08; Java 档案文件&#xff09;&#xff0c;它是 Java 的一种文档格式JAR 文件与 ZIP 文件唯一的区别就是在 JAR 文件的内容中&#xff0c;多出了一个META-INF/MANIFEST.MF 文件META-INF/MANIFEST.MF 文件在生成 JAR 文件的时候…

软件工程第20、21章小测

单项选择题 第1题 传统的软件交付方式&#xff0c;有什么弊端&#xff08;&#xff09;。 用户不参与开发过程的决策。 用户对交付的软件会经常性的提出修改意见和新的需求。 &#xff08;我的答案&#xff09; 维护困难。 交付困难。 第2题 渐进式的交付方式&#xff…

多目标优化算法——多目标粒子群优化算法(MOPSO)

Handling Multiple Objectives With Particle Swarm Optimization&#xff08;多目标粒子群优化算法&#xff09; 一、摘要&#xff1a; 本文提出了一种将帕累托优势引入粒子群优化算法的方法&#xff0c;使该算法能够处理具有多个目标函数的问题。与目前其他将粒子群算法扩展…

游戏引擎学习第22天

移除 DllMain() 并成功重新编译 以下是对内容的详细复述与总结&#xff1a; 问题和解决方案&#xff1a; 在编译过程中遇到了一些问题&#xff0c;特别是如何告知编译器不要退出程序&#xff0c;而是继续处理。问题的根源在于编译过程中传递给链接器的参数设置不正确。原本尝试…

LeetCode数组题

参考链接 代码随想录 讲解视频链接 数组题 1、(两数之和)给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。你可以假设每种输入只会对应一个答案&#xff0c;并且你不能使用…

Windows修复SSL/TLS协议信息泄露漏洞(CVE-2016-2183) --亲测

漏洞说明&#xff1a; 打开链接&#xff1a;https://docs.microsoft.com/zh-cn/troubleshoot/windows-server/windows-security/restrict-cryptographic-algorithms-protocols-schannel 可以看到&#xff1a; 找到&#xff1a;应通过配置密码套件顺序来控制 TLS/SSL 密码 我们…

捉虫笔记(七)-再探谁把系统卡住了

捉虫笔记&#xff08;七&#xff09;-再探谁把系统卡住 1、内核调试 在实体物理机上&#xff0c;内核调试的第一个门槛就是如何建立调试链接。 这里我选择的建立网络连接进行内核调试。 至于如何建立网络连接后续文章再和大家分享。 2、如何分析 在上一篇文章中&#xff0c;我们…

追加docker已运行容器添加或修改端口映射方法

docker run可以指定端口映射 【】docker run -d -p 80:80 --name name 但是容器一旦生成&#xff0c;就没有一个命令可以直接修改。通常间接的办法是&#xff0c;保存镜像&#xff0c;再创建一个新的容器&#xff0c;在创建时指定新的端口映射。 【】 docker stop A 【】 doc…