如何将单元格模板传递给带有b表的组件? [英] How to pass cell templates to a component with b-table?

查看:102
本文介绍了如何将单元格模板传递给带有b表的组件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个显示各个页面的表数据的组件.该组件在内部使用 b表.现在,对于几个页面,我想自定义一些列的呈现,并且引导表允许使用带特殊语法的作用域字段槽:

I created a component that shows table data for various pages. That component uses b-table inside. Now for a couple pages I want to customize rendering of some columns, and Bootstrap Tables allow that using scoped field slots with special syntax:

    <template #cell(field)="data">
            {{ data.item.value }}
    </template>

其中field-列名,来自我带有列的数组,以及data.item-要呈现的单元格项.

where field - column name, coming from my array with columns, and data.item - cell item to be rendered.

问题是我在不同页面上有不同的字段,因此此自定义应来自父组件,并且这些模板应动态创建.

The problem is that I have different fields for different pages, so this customization should come from parent component, and these templates should be created dynamically.

这是我尝试解决的方法:

Here is how I tried to solve it:

通过属性将具有可自定义字段和唯一插槽名称的数组传递给MyTableComponent在MyTableComponent中动态创建用于自定义的模板,并在内部动态创建命名的插槽

Pass via property to MyTableComponent an array with customizable fields and unique slot names In MyTableComponent dynamically create templates for customization, and inside dynamically create named slots

从父级传递插槽数据到命名插槽

From parent pass slot data to named slots

MyTableComponent:

    <b-table>
        <template v-for="slot in myslots" v-bind="cellAttributes(slot)">
            <slot :name="slot.name"></slot>
        </template>
    </b-table>

    <script>
        ...
        computed: {
            cellAttributes(slot) {
                return ['#cell(' + slot.field + ')="data"'];
            }
        }
        ...
    </script>

父母:

    <MyTableComponent :myslots="myslots" :items="items" :fields="fields">
        <template slot="customSlot1">
                Hello1
        </template>
        <template slot="customSlot1">
                Hello2
        </template>
    </MyTableComponent>

<script>
    ...
    items: [...my items...],
    fields: [...my columns...],
    myslots: [
        { field: "field1", name: "customSlot1" },
        { field: "field2", name: "customSlot2" }
    ]
    ...
</script>

不幸的是, b表组件只是忽略了我的自定义插槽,就像没有提供它们一样.如果我直接在MyTableComponent中指定它,它将起作用:

Unfortunately, b-table component just ignores my custom slots like if they are not provided. It works if I specify in the MyTableComponent it directly:

    <b-table>
          <template #cell(field1)="data">
            {{ data.item.value }}
          </template>
    </b-table>

但是我需要通过组件属性动态地完成它.请帮忙.

But I need it to be done dynamically via component properties. Please help.

推荐答案

您可以使用 Vue 2的动态插槽名称功能可将所有(或某些)插槽从父级传递到子级内部的< b-table> ,如下所示:

You can use Dynamic Slot Names feature of Vue 2 to pass all (or some) slots from parent to <b-table> inside child like this:

孩子:

<b-table>
  <template v-for="(_, slotName) of $scopedSlots" v-slot:[slotName]="scope">
    <slot :name="slotName" v-bind="scope"/>
  </template>
</b-table>

$ scopedSlots 包含传递给组件的所有插槽.

$scopedSlots contains all slots passed to your component.

现在这将起作用:

    <MyTableComponent :items="items" :fields="fields">
          <template #cell(field1)="data">
            {{ data.item.value }}
          </template>
    </ MyTableComponent>

更新

如果需要,可以通过创建 compute 来对其进行过滤(不想将其传递给< b-table> 的包装器组件有特定的插槽)

You can filter it if you want (have some slot specific to your wrapper component you don't want to pass down to <b-table>) by creating computed

我在最初的回答中提到了这种可能性,但这有点问题,因此值得更好的解释...

I mentioned this possibility in my original answer but it is a bit problematic so it deserves better explanation...

  1. 作用域内的插槽作为函数传递给组件(在调用时生成VNode).目标组件只是执行(通过名称)她所知道的那些,而忽略其余部分.因此,可以说您的包装器内部有 b-table (或Vuetify的 v-data-table )和其他一些组件,比如说分页.您可以在两个代码中使用上面的代码,并将所有插槽传递给每个代码.除非存在命名冲突(两个组件都使用相同的插槽名称),否则它将正常工作并且不会引起任何额外的开销(将所有插槽函数传递给包装器组件时都已编译/创建).目标组件将仅使用(执行)其名称已知的插槽.

  1. Scoped slots are passed to a component as a functions (generating VNode's when called). Target component just executes those she knows about (by name) and ignores the rest. So lets say your wrapper has b-table (or v-data-table for Vuetify) inside and some other component, let's say pagination. You can use code above inside both of them, passing all slots to each. Unless there is some naming conflict (both components using same slot name), it will work just fine and does not induce any additional cost (all slot functions are already compiled/created when passed to your wrapper component). Target component will use (execute) only the slots it knows by name.

如果可能存在命名冲突,可以使用一些命名约定来解决,例如为仅用于 b-table 的插槽名称加上前缀 table-并在内部进行过滤,但要注意 $ scopedSlots 对象确实包含一些Vue内部属性,这些属性必须沿着!! ( $ stable $ key $ hasNormal -请参见

If there is possible naming conflict, it can be solved by using some naming convention like prefixing slot names intended just for b-table with something like table-- and doing filtering inside but be aware that $scopedSlots object does contain some Vue internal properties which must be copied along !! ($stable, $key and $hasNormal for Vue 2 - see the code). So the filtering code below even it's perfectly fine and doesn't throw any error will not work (b-table will not recognize and use the slots)

<b-table>
  <template v-for="(_, slotName) of tableSlots" v-slot:[slotName]="scope">
    <slot :name="slotName" v-bind="scope"/>
  </template>
</b-table>

computed: {
    tableSlots() {
      const prefix = "table--";
      const raw = this.$scopedSlots;
      const filtered = Object.keys(raw)
        .filter((key) => key.startsWith(prefix))
        .reduce(
          (obj, key) => ({
            ...obj,
            [key.replace(prefix, "")]: raw[key],
          }),
          {}
        );
      return filtered;
    },
  },

可以通过包含上面提到的属性来修复此代码,但是根据我的喜好,它对Vue内部实现的依赖性太大,因此我不建议这样做.如果可能,请坚持方案1 ...

This code can be fixed by including the properties mentioned above but this just too much dependency on Vue internal implementation for my taste and I do not recommend it. If it's possible, stick with the scenario 1...

这篇关于如何将单元格模板传递给带有b表的组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆