将插槽传递到 Vue.js 中的插槽
Posted
技术标签:
【中文标题】将插槽传递到 Vue.js 中的插槽【英文标题】:Passing slot into slot in Vue.js 【发布时间】:2020-06-05 22:15:48 【问题描述】:我正在尝试将 slot 传递到 slot 中,但是需要向下传递 slot 的子组件看不到它。
在子 (TheTable) 中,我有来自 Core UI for Vue (CDataTable) 的表格组件,它需要我想从父级传递的某些插槽:
<CDataTable
class="overflow-auto"
:items="this.items"
:fields="fieldData"
:sorter=" external: true, resetable: true "
:sorter-value="this.sorterValue"
:table-filter=" external: true, lazy: false, placeholder: 'Enter here', label: 'Search:'"
:responsive="false"
:loading="this.loading"
:hover="true"
:items-per-page-select="true"
:items-per-page="this.perPage"
@pagination-change="paginationChanged"
@update:sorter-value="sorterUpdated"
@update:table-filter-value="filterUpdated"
>
<slot name="requiredTableFields"></slot>
</CDataTable>
在我的父组件中:
<TheTable
v-bind:fields="fields"
v-bind:endpoint-url="endpointUrl"
>
<template slot="requiredTableFields">
<td slot="name" slot-scope="item">
<div> item['attributes.email'] </div>
<div class="small text-muted">
item['attributes.firstname'] item['attributes.lastname']
</div>
</td>
<td slot="registered" slot-scope="item">
<template v-if="item['attributes.created_at']"> item['attributes.created_at'] </template>
<template v-else>Not setup yet</template>
</td>
</template>
</TheTable>
有什么办法让它工作吗? 干杯, 卡斯珀
【问题讨论】:
vue 2.6 有一个新的waytemplate v-slot:requiredTableFields
遗憾的是没有运气,问题似乎在于桌子没有看到它的插槽......
CDataTable 需要为其插槽提供模板。您需要先设置预期的模板。我认为您正在尝试从父组件传递此模板对吗?。
是的,我正在尝试从父母那里传递它们。实际上无法在那里设置这些模板,因为它们会有所不同,带有 CDataTable 的组件将用于抽象。
我不认为这是可能的,但您可以尝试使用以下库 github.com/LinusBorg/portal-vue
【参考方案1】:
将基础插槽合并到单个 requiredTableFields
插槽中是行不通的,因为一旦子插槽被合并,就没有(简单的)方法可以将它们分开。
相反,您可以将插槽分开:
<TheTable ...>
<template v-slot:name=" item ">
<td>
...
</td>
</template >
<template v-slot:registered=" item ">
<td>
...
</td>
</template>
</TheTable>
这会将两个作用域插槽 name
和 registered
传递到 TheTable
。
假设您不想将插槽名称硬编码为 TheTable
,那么您需要遍历 $scopedSlots
以动态包含它们。
<CDataTable ...>
<template v-for="(x, slotName) in $scopedSlots" v-slot:[slotName]="context">
<slot :name="slotName" v-bind="context" />
</template>
</CDataTable>
对此的一些说明:
x
没有被使用,我们只需要遍历插槽名称。
与作用域槽关联的“数据”称为context
,只是被传递。
如果插槽不是作用域插槽,它会略有不同。我们将迭代 $slots
并删除所有引用 context
的部分。
在:name
属性的开头有一个:
,因为我们要传递一个动态名称。不幸的是,原始问题中的一个位置也称为name
,这可能会导致一些混乱。
v-bind="context"
部分类似于 javascript 扩展运算符,如果这样更清楚的话。把它想象成attributes = name: slotName, ...context
。
下面是一个完整的示例,说明了上述技术。它没有使用CDataTable
,但传递slots的核心原理是完全一样的。
const Comp2 =
template: `
<div>
<h4>Left</h4>
<div><slot name="top" item="Red" /></div>
<h4>Right</h4>
<div><slot name="bottom" item="Green" /></div>
</div>
`
const Comp1 =
template: `
<div>
<comp2>
<template v-for="(x, slotName) in $scopedSlots" v-slot:[slotName]="context">
<slot :name="slotName" v-bind="context" />
</template>
</comp2>
</div>
`,
components:
Comp2
new Vue(
el: '#app',
components:
Comp1
)
<script src="https://unpkg.com/vue@2.6.11/dist/vue.js"></script>
<div id="app">
<comp1>
<template v-slot:top=" item ">
<button>Slot 1 - item </button>
</template>
<template v-slot:bottom=" item ">
<button>Slot 2 - item </button>
</template>
</comp1>
</div>
【讨论】:
以上是关于将插槽传递到 Vue.js 中的插槽的主要内容,如果未能解决你的问题,请参考以下文章