props、emits、attrs、插槽如何设计组件接口?

先理解原理和示例,再练习完整口述与追问。

明确输入、事件和内容定制边界;声明 props / emits,按需要透传 attrs。多根节点等情况下不能依赖隐式透传。组件实例对外暴露的方法应少且稳定。

组件接口先定义输入数据、允许事件和渲染扩展点。props 声明可配置数据,emits 声明对外行为,slots 让调用方定制展示;attrs 是未被声明为 prop/emits 等处理的透传属性。根节点结构、inheritAttrs 与是否显式绑定 attrs 决定透传落到哪里,多根节点时不能期待框架替你猜所有属性归属。

封装输入组件时,value/modelValue、disabled 是明确输入,change/update 是明确事件,label 或 suffix 可作为插槽。若外层只是包装布局,应把合适的 attrs 与原生属性交给真实 input,而不是都落到外层 div,导致 placeholder、aria-label 和焦点行为失效。外部 click 监听是否被当成组件事件,也取决于声明与实现。

不要无差别 v-bind 全部对象给 DOM,避免泄露内部字段和错误属性。组件“可复用”不等于把任意样式、权限、请求都耦合到同一个万能接口。

组件接口我分成数据输入、事件输出和插槽内容三部分。props 表达依赖,emits 表达业务通知,attrs 仅按需要透传到目标 DOM。多根节点或包装结构中要明确 class、disabled、监听器落到哪个元素,不能依赖自动落位。对子组件实例的方法访问通过 expose 限制,只开放聚焦、校验等稳定能力。

面试官可能继续问追问与完整解答展开收起

为什么事件被重复触发?封装输入框时 class、disabled、监听器分别应该落到哪里?

如果没有正确声明组件事件,又同时把监听器透传到内部原生节点并手动 emit,父级可能重复收到通知。class 往往给外观根节点,disabled 应落到实际控件,监听器按约定转发;包装组件可关闭自动继承后逐项绑定,避免意外附着。