You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3可复用表格组件:能否隐式传递slotProps替代显式传递?

实现Vue3表格组件slotProps隐式传递的方案

当然可以去掉显式传递slotProps的步骤,下面给你两种实用的实现思路:

方法一:利用Vue3的Provide/Inject API

这是最直接的方式,在FSTable组件内部把需要传递的slotProps通过provide暴露出去,然后在FSTableColumn组件里用inject接收,就能实现隐式传递了。

具体代码示例

  1. FSTable组件内部:
<script setup>
import { provide } from 'vue'
// 假设这是你原本要传给slotProps的内容
const tableSlotProps = {
  headerData: /* 表头数据 */,
  cellData: /* 单元格数据 */,
  // 其他需要传递的属性
}
// 把slotProps提供给子组件
provide('tableSlotProps', tableSlotProps)
</script>

<template>
  <table>
    <thead>
      <tr>
        <!-- 这里不再需要显式传递slotProps,FSTableColumn会自己inject -->
        <slot name="header"></slot>
      </tr>
    </thead>
    <tbody>
      <tr v-for="item in data" :key="item.id">
        <slot name="cell" :item="item"></slot>
      </tr>
    </tbody>
  </table>
</template>
  1. FSTableColumn组件内部:
<script setup>
import { inject } from 'vue'
// 注入FSTable提供的slotProps
const tableSlotProps = inject('tableSlotProps', {}) // 加默认值避免非FSTable环境报错
const props = defineProps({
  prop: String,
  renderAs: String
})
// 结合renderAs处理渲染逻辑
const renderContent = () => {
  if (props.renderAs === 'header') {
    return tableSlotProps.headerData?.[props.prop]
  } else {
    return tableSlotProps.cellData?.[props.prop]
  }
}
</script>

<template>
  <td v-if="renderAs === 'cell'">{{ renderContent() }}</td>
  <th v-else>{{ renderContent() }}</th>
</template>

使用时无需显式传递slotProps,直接写:

<FSTable :data="tableData">
  <template #header>
    <FSTableColumn prop="name" renderAs="header" />
    <FSTableColumn prop="age" renderAs="header" />
  </template>
  <template #cell="{ item }">
    <FSTableColumn prop="name" renderAs="cell" />
    <FSTableColumn prop="age" renderAs="cell" />
  </template>
</FSTable>

方法二:封装作用域插槽的子组件逻辑

如果不想用provide/inject,也可以在FSTable里自动处理插槽内容,给所有FSTableColumn子组件绑定所需的slotProps。

具体代码示例

FSTable组件内部:

<script setup>
import { h, useSlots } from 'vue'
const slots = useSlots()
const props = defineProps({
  data: {
    type: Array,
    required: true
  },
  headerData: {
    type: Object,
    required: true
  }
})

// 处理表头插槽,自动给FSTableColumn传递slotProps
const renderHeader = () => {
  const headerSlot = slots.header?.() || []
  return headerSlot.map(vnode => {
    // 通过组件名称识别FSTableColumn
    if (vnode.type.name === 'FSTableColumn') {
      vnode.props = {
        ...vnode.props,
        slotProps: { headerData: props.headerData }
      }
    }
    return vnode
  })
}

// 处理单元格插槽,同理
const renderCell = (item) => {
  const cellSlot = slots.cell?.({ item }) || []
  return cellSlot.map(vnode => {
    if (vnode.type.name === 'FSTableColumn') {
      vnode.props = {
        ...vnode.props,
        slotProps: { cellData: item }
      }
    }
    return vnode
  })
}
</script>

<template>
  <table>
    <thead>
      <tr>
        <render-header />
      </tr>
    </thead>
    <tbody>
      <tr v-for="item in data" :key="item.id">
        <render-cell :item="item" />
      </tr>
    </tbody>
  </table>
</template>

这种方式下,使用组件的写法和第一种方法完全一致,无需手动传递slotProps。

注意事项

  • 用provide/inject时,务必给inject设置默认值,避免FSTableColumn在非FSTable内部使用时出现报错。
  • 第二种方法依赖组件名称识别,如果后续修改组件名称,要同步调整判断逻辑,也可以给FSTableColumn加一个自定义属性(比如isTableColumn)来做更可靠的识别。

内容的提问来源于stack exchange,提问作者Daniel P.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 06:03:26