在渲染函数中构建动态数量的 Vue 插槽
Build a dynamic number of Vue slots within a Render function
我正在尝试从渲染函数构建自定义组件。
正在呈现的这个组件接受任意数量的插槽。在下面的示例中,有三个可用插槽(名为 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') }}), {})
});
},
但是没有任何渲染,也没有任何错误可以指导我。有什么想法吗?
该 reduce 方法不起作用,因为它在 createElement('div', 'hello world')
:
之前缺少 return
完整示例
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>
我认为作用域插槽应该是将 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>
不同之处在于,在您的 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>
我正在尝试从渲染函数构建自定义组件。
正在呈现的这个组件接受任意数量的插槽。在下面的示例中,有三个可用插槽(名为 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') }}), {})
});
},
但是没有任何渲染,也没有任何错误可以指导我。有什么想法吗?
该 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>
我认为作用域插槽应该是将 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>
不同之处在于,在您的 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>