在 Render 函数中构建动态数量的 Vue 插槽
Posted
技术标签:
【中文标题】在 Render 函数中构建动态数量的 Vue 插槽【英文标题】:Build a dynamic number of Vue slots within a Render function 【发布时间】:2021-03-14 15:00:12 【问题描述】:我正在尝试从渲染函数构建自定义组件。
这个正在渲染的组件接受任意数量的插槽。在下面的示例中,有三个可用的插槽(名为 element_1
、element_2
、element_3
)。
下面的Array.reduce()
等同于:
scopedSlots:
"element_1": () => createElement('div', 'hello world'),
"element_2": () => createElement('div', 'hello world'),
"element_3": () => createElement('div', 'hello world'),
这是Array.reduce()
的精简示例:
const records = [
"index": 1,
,
"index": 2,
,
"index": 3,
]
render: function (createElement)
return createElement("replicator-component",
attrs: elements: records.length,
scopedSlots: records.reduce((a,x) => (...a,
['element_' + x.index]:
() => createElement( 'div', 'hello world') ), )
);
,
但是没有任何渲染,也没有错误可以指导我。有什么想法吗?
【问题讨论】:
【参考方案1】:不同之处在于,在您的reduce
中,您将函数创建为
() => createElement( 'div', 'hello world')
在您的硬编码版本中(以及在@Boussadjra 的答案中的forEach
循环中),它们被创建为
() => createElement('div', 'hello world')
实际上是 return
创建的元素。和reduce
的使用无关,没关系。
const ReplicatorComponent =
template: `<div>
<h1>replicator-component</h1>
<slot name='element_1'></slot>
<slot name='element_2'></slot>
<slot name='element_3'></slot>
</div>`
;
const records = [
"index": 1 ,
"index": 2 ,
"index": 3 ,
];
Vue.component('my-component',
render: function(createElement)
return createElement(ReplicatorComponent,
attrs:
elements: records.length
,
scopedSlots: records.reduce((a,x) => (
...a,
['element_' + x.index]: () =>
createElement( 'div', 'hello world')
), )
);
,
);
new Vue(
el: '#app',
data: () => ()
);
<script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
<div id="app">
<my-component></my-component>
</div>
【讨论】:
【参考方案2】:我认为作用域插槽应该是以props
作为参数的函数
根据 Vue.js 文档
export default
render(createElement)
// ...
// some other stuff
// ...
// Scoped slots in the form of
// name: props => VNode | Array<VNode>
scopedSlots:
default: props => createElement('span', props.text)
,
所以也许你应该尝试一下
你也可以使用 vue 新的统一 v-slot
系统来完成同样的事情
<!-- page component -->
<template>
<some-component>
<template v-for="slot in scopedSlots" v-slot:[slot]="props">
hello props
</template>
</some-component>
</template>
<!-- some-component.vue -->
<template>
<div>
<slot v-for="slot in Object.keys($slots)" :name="slot"></slot>
</div>
</template>
【讨论】:
【参考方案3】:reduce 方法不起作用,因为它在createElement('div', 'hello world')
之前缺少返回:
完整示例
const ReplicatorComponent =
template: `
<div>
<h1>replicator-component</h1>
<slot name='element_1'></slot>
<slot name='element_2'></slot>
<slot name='element_3'></slot>
</div>
`
const records = [
"index": 1,
,
"index": 2,
,
"index": 3,
]
Vue.component('my-component',
render: function(createElement)
let slotContent = records.reduce((a, x) => ( ...a,
['element_' + x.index]:
() =>
return createElement('div', 'hello world')
), )
return createElement(ReplicatorComponent,
attrs:
elements: records.length
,
scopedSlots: slotContent
);
,
)
var app = new Vue(
el: '#app',
data: () => ()
)
<script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
<div id="app">
test
<my-component></my-component>
</div>
【讨论】:
以上是关于在 Render 函数中构建动态数量的 Vue 插槽的主要内容,如果未能解决你的问题,请参考以下文章