使用Vue3 TSX 插槽,让组件复用更灵活
YGHub·2024-11-19·1·字数:293 字·阅读时间:1 分钟
在 Vue3 中使用 TSX
开发时,插槽的使用方式与模板语法有些不同。如何在 TSX
中优雅地使用插槽,让组件更具复用性!
一、基础用法
1. 默认插槽
jsx
// 定义组件const Card = (props, { slots }) => { return ( <div class="card"> <div class="card-content"> {slots.default?.()} </div> </div> )} // 使用组件const App = () => { return ( <Card> <div>这是默认插槽内容</div> </Card> )}
2. 具名插槽
jsx
// 定义组件const Layout = (props, { slots }) => { return ( <div class="layout"> <header>{slots.header?.()}</header> <main>{slots.default?.()}</main> <footer>{slots.footer?.()}</footer> </div> )} // 使用组件const App = () => { return ( <Layout> {{ header: () => <h1>页面标题</h1>, default: () => <div>主要内容</div>, footer: () => <div>页脚内容</div> }} </Layout> )}
二、作用域插槽
1. 基本使用
jsx
// 定义组件interface ListProps { items: string[]} const List = (props: ListProps, { slots }) => { return ( <div class="list"> {props.items.map((item, index) => ( slots.default?.({ item, index }) ))} </div> )} // 使用组件const App = () => { const items = ['苹果', '香蕉', '橙子'] return ( <List items={items}> {({ item, index }) => ( <div class="item"> {index + 1}: {item} </div> )} </List> )}
2. 类型定义
jsx
// 定义插槽类型interface SlotProps { item: string index: number} interface ListSlots { default: (props: SlotProps) => any} // 使用类型const List = (props: ListProps, { slots }: { slots: ListSlots }) => { return ( <div class="list"> {props.items.map((item, index) => ( slots.default({ item, index }) ))} </div> )}
三、高级用法
1. 条件渲染插槽
jsx
const Card = (props, { slots }) => { return ( <div class="card"> {slots.title?.() && ( <div class="card-title"> {slots.title?.()} </div> )} <div class="card-content"> {slots.default?.()} </div> {slots.footer?.() && ( <div class="card-footer"> {slots.footer?.()} </div> )} </div> )}
2. 插槽默认内容
jsx
const Button = (props, { slots }) => { return ( <button class="btn"> {slots.default?.() || '点击'} </button> )}
3. 动态插槽
jsx
const DynamicLayout = (props, { slots }) => { const slotNames = ['header', 'content', 'footer'] return ( <div class="dynamic-layout"> {slotNames.map(name => ( <div class={`section-${name}`}> {slots[name]?.()} </div> ))} </div> )}
四、实战示例
1. 表格组件
jsx
interface TableColumn { key: string title: string} interface TableProps { columns: TableColumn[] data: any[]} const Table = (props: TableProps, { slots }) => { return ( <table> <thead> <tr> {props.columns.map(column => ( <th key={column.key}> {slots[`header-${column.key}`]?.() || column.title} </th> ))} </tr> </thead> <tbody> {props.data.map((row, index) => ( <tr key={index}> {props.columns.map(column => ( <td key={column.key}> {slots[`cell-${column.key}`]?.({ row, index }) || row[column.key]} </td> ))} </tr> ))} </tbody> </table> )}
2. 弹窗组件
jsx
interface ModalProps { visible: boolean onClose: () => void} const Modal = (props: ModalProps, { slots }) => { return ( <Teleport to="body"> {props.visible && ( <div class="modal-wrapper"> <div class="modal"> <div class="modal-header"> {slots.header?.() || <h3>提示</h3>} </div> <div class="modal-content"> {slots.default?.()} </div> <div class="modal-footer"> {slots.footer?.() || ( <button onClick={props.onClose}>关闭</button> )} </div> </div> </div> )} </Teleport> )}
五、最佳实践
1. 类型定义
jsx
// 定义插槽类型type DefaultSlotType = () => any interface CustomSlots { default?: DefaultSlotType [key: string]: DefaultSlotType | undefined} // 组件定义interface ComponentProps { // props 类型} const Component = ( props: ComponentProps, { slots }: { slots: CustomSlots }) => { // 组件实现}
2. 插槽工具函数
jsx
// 工具函数const renderSlot = (slot: undefined | (() => any), defaultContent?: any) => { return slot?.() || defaultContent} // 使用示例const Component = (props, { slots }) => { return ( <div> {renderSlot(slots.default, <div>默认内容</div>)} </div> )}
3. 组合使用
jsx
// 复杂组件示例const ComplexComponent = (props, { slots }) => { return ( <div class="complex-component"> {/* 条件渲染 */} {slots.header && ( <header class="header"> {renderSlot(slots.header)} </header> )} {/* 作用域插槽 */} <main class="content"> {props.items.map((item, index) => ( renderSlot( slots.item, { item, index }, <div class="default-item">{item.name}</div> ) ))} </main> {/* 默认内容 */} <footer class="footer"> {renderSlot(slots.footer, <div>默认页脚</div>)} </footer> </div> )}
总结
在 Vue3 TSX 中使用插槽需要注意以下几点:
1.基础用法:
- 通过
slots
参数访问插槽 - 使用可选链调用插槽函数
- 支持具名插槽和默认插槽
2.类型支持:
- 定义清晰的插槽类型
- 使用
TypeScript
提供类型检查 - 注意插槽函数的返回类型
3.最佳实践:
- 提供合理的默认内容
- 使用工具函数简化代码
- 保持组件的可复用性
Preview
1
点个赞 ~
版权申明: © 本文著作权归YGHub所有,未经YGHub网授权许可,禁止第三方以任何形式转载和使用本文内容。
Related article
基于微信小程序实现图片压缩、裁剪、尺寸调整的实践总结
YGHub
2025-01-02
4
Vue3 作用域插槽,提升组件复用性的利器
YGHub
2024-12-03
1
Nuxt3 中使用 localStorage 的正确姿势
YGHub
2024-12-01
3
Vue3 子组件 defineExpose 暴露方法无效的三种常见场景及解决方案
YGHub
2024-11-24
7
Vue3 组件通信实战,实现跨组件数据更新
YGHub
2024-11-21
8