基础篇三 Nuxt4 组件进阶:插槽与事件传递

张开发
2026/4/10 14:56:18 15 分钟阅读

分享文章

基础篇三 Nuxt4 组件进阶:插槽与事件传递
文章目录一、插槽基础二、默认内容三、具名插槽四、作用域插槽五、高阶表格组件六、事件传递emit七、v-model 双向绑定八、多个 v-model九、透传属性十、组件引用总结写过 Vue 的同学都知道组件通信是个大话题。props 向下传emit 向上发听起来简单但实际项目中各种复杂场景让人头大。今天深入聊聊组件间通信的进阶技巧——插槽和事件传递。一、插槽基础插槽让组件的内容可以由父组件决定!-- components/MyCard.vue -- template div classcard slot / /div /template style scoped .card { border: 1px solid #eee; border-radius: 8px; padding: 1rem; } /style使用时MyCard h2标题/h2 p这是卡片内容/p /MyCard二、默认内容插槽可以设置默认内容父组件不传时显示!-- components/MyButton.vue -- template button classbtn slot 点击我 !-- 默认内容 -- /slot /button /template!-- 使用默认内容 -- MyButton / !-- 覆盖默认内容 -- MyButton提交/MyButton三、具名插槽一个组件可能有多个区域需要填充!-- components/ArticleCard.vue -- template article classarticle-card header slot nameheader / /header main slot / !-- 默认插槽 -- /main footer slot namefooter / /footer /article /template使用ArticleCard template #header h2文章标题/h2 /template p文章正文内容.../p template #footer span2024-01-15/span /template /ArticleCard四、作用域插槽父组件想用子组件的数据怎么办作用域插槽!-- components/UserList.vue -- script setup langts const users [ { id: 1, name: Alice, age: 25 }, { id: 2, name: Bob, age: 30 }, { id: 3, name: Charlie, age: 35 } ] /script template ul li v-foruser in users :keyuser.id slot :useruser :indexuser.id {{ user.name }} !-- 默认渲染 -- /slot /li /ul /template父组件自定义渲染UserList template #default{ user, index } span{{ index }}. {{ user.name }} ({{ user.age }}岁)/span /template /UserList五、高阶表格组件作用域插槽最经典的场景是表格组件!-- components/DataTable.vue -- script setup langts interface Column { key: string title: string } const props defineProps{ columns: Column[] data: any[] }() /script template table thead tr th v-forcol in columns :keycol.key {{ col.title }} /th /tr /thead tbody tr v-for(row, index) in data :keyindex td v-forcol in columns :keycol.key slot :namecol.key :rowrow :valuerow[col.key] {{ row[col.key] }} /slot /td /tr /tbody /table /template使用script setup langts const columns [ { key: name, title: 姓名 }, { key: age, title: 年龄 }, { key: actions, title: 操作 } ] const users [ { id: 1, name: Alice, age: 25 }, { id: 2, name: Bob, age: 30 } ] /script template DataTable :columnscolumns :datausers !-- 自定义年龄列 -- template #age{ value } span :class{ text-red: value 28 } {{ value }}岁 /span /template !-- 自定义操作列 -- template #actions{ row } button clickedit(row)编辑/button button clickdelete(row)删除/button /template /DataTable /template六、事件传递emit子组件向父组件传数据用emit!-- components/Counter.vue -- script setup langts const count ref(0) const emit defineEmits{ change: [value: number] reset: [] }() const increment () { count.value emit(change, count.value) } const reset () { count.value 0 emit(reset) } /script template div p计数: {{ count }}/p button clickincrement1/button button clickreset重置/button /div /template父组件监听script setup langts const handleChange (value: number) { console.log(计数变化:, value) } const handleReset () { console.log(已重置) } /script template Counter changehandleChange resethandleReset / /template七、v-model 双向绑定v-model本质是:valueupdate:value的语法糖!-- components/SearchInput.vue -- script setup langts const props defineProps{ modelValue: string }() const emit defineEmits{ update:modelValue: [value: string] }() const input (e: Event) { emit(update:modelValue, (e.target as HTMLInputElement).value) } /script template input :valuemodelValue inputinput placeholder搜索... / /template使用script setup langts const keyword ref() /script template SearchInput v-modelkeyword / p搜索词: {{ keyword }}/p /templateVue 3.4 可以用defineModel简化!-- components/SearchInput.vue -- script setup langts const keyword defineModelstring() /script template input v-modelkeyword placeholder搜索... / /template八、多个 v-model一个组件可以有多个双向绑定!-- components/DateRange.vue -- script setup langts const startDate defineModelDate(startDate) const endDate defineModelDate(endDate) /script template div classdate-range input typedate v-modelstartDate / span至/span input typedate v-modelendDate / /div /template使用script setup langts const start refDate() const end refDate() /script template DateRange v-model:start-datestart v-model:end-dateend / /template九、透传属性有时候组件只是一个包装器需要把所有属性传给内部元素!-- components/MyButton.vue -- script setup langts // 不声明 props属性会自动透传到根元素 /script template button classmy-button slot / /button /template使用时type、disabled等属性会自动传给buttonMyButton typesubmit disabled提交/MyButton渲染结果buttonclassmy-buttontypesubmitdisabled提交/button禁用透传script setup langts defineOptions({ inheritAttrs: false }) const attrs useAttrs() /script template div input v-bindattrs / /div /template十、组件引用有时候需要调用子组件的方法!-- components/Modal.vue -- script setup langts const visible ref(false) const open () { visible.value true } const close () { visible.value false } // 暴露方法给父组件 defineExpose({ open, close }) /script template Teleport tobody div v-ifvisible classmodal slot / button clickclose关闭/button /div /Teleport /template父组件script setup langts const modalRef ref{ open: () void; close: () void }() const showModal () { modalRef.value?.open() } /script template button clickshowModal打开弹窗/button Modal refmodalRef h2弹窗内容/h2 /Modal /template总结组件通信技巧汇总方式方向场景Props父→子传递数据Emit子→父传递事件v-model双向表单组件插槽父→子内容分发作用域插槽子→父子组件数据供父组件渲染defineExpose父→子调用子组件方法下一篇聊聊全局样式与 CSS 模块让你的样式管理更规范。相关文章入门篇三Nuxt4组件自动导入写代码少敲一半字入门篇二Nuxt 4路由自动生成告别手动配置路由的日子延伸阅读nuxt4完整系列持续更新中。。欢迎来逛逛内容有帮助点赞、收藏、关注三连评论区等你

更多文章