如何在Vuejs渲染函数中复制插槽?

时间:2018-06-27 14:17:46

标签: vue.js vuejs2 vue-component

我有一个通过插槽传递内容的组件。我正在使用一个render函数来输出内容。我使用渲染功能的原因是因为我想多次复制内容。当我使用此代码时,一切正常:

render(createElement){
    return createElement('div', {}, this.$slots.default);
}

当我传递的数据发生变化时,输出也会发生变化。

但是,由于我要复制广告位内容,因此我现在尝试这样做:

return createElement(
    'div', {},
        [
            createElement('div', { }, this.$slots.default),
            createElement('div', { }, this.$slots.default)
        ]
    )

现在的问题是,当插槽内容从组件外部更改时,只有第二个div中的内容得到更新,而第一个div中的内容保持不变。

我在这里想念东西吗?

2 个答案:

答案 0 :(得分:1)

我无法解释为什么会发生。但是文档确实在渲染函数中提到了VNodes Must Be Unique。参见https://vuejs.org/v2/guide/render-function.html#Constraints

无论如何,这是一个有效的Vnode克隆功能,我从https://jingsam.github.io/2017/03/08/vnode-deep-clone.html中发现了该功能。

function deepClone(vnodes, createElement) {
    function cloneVNode(vnode) {
        const clonedChildren = vnode.children && vnode
            .children
            .map(vnode => cloneVNode(vnode));
        const cloned = createElement(vnode.tag, vnode.data, clonedChildren);
        cloned.text = vnode.text;
        cloned.isComment = vnode.isComment;
        cloned.componentOptions = vnode.componentOptions;
        cloned.elm = vnode.elm;
        cloned.context = vnode.context;
        cloned.ns = vnode.ns;
        cloned.isStatic = vnode.isStatic;
        cloned.key = vnode.key;
        return cloned;
    }
    const clonedVNodes = vnodes.map(vnode => cloneVNode(vnode))
    return clonedVNodes;
}

如何使用它:

render(createElement) {
    return createElement('div', {}, [
        createElement('div', {}, this.$slots.default),
        createElement('div', {}, [...deepClone(this.$slots.default, createElement)])
    ])
}

演示:https://jsfiddle.net/jacobgoh101/bz3e0o5m/

答案 1 :(得分:0)

我发现了这个SO问题,正在寻找一种方法来多次渲染广告位的内容,例如一个通用列表,该列表可以具有用于每个项目的列表行内容的模板。

从2020年开始(实际上是更早的时候),可以使用范围内的广告位来实现广告位的多次渲染。在此处记录:

https://vuejs.org/v2/guide/components-slots.html#Other-Examples

文档说:

广告位道具使我们能够将广告位变成可重复使用的模板,这些模板可以根据输入的道具来呈现不同的内容

(显然,如果我们可以使用模板根据道具来呈现不同的内容,那么我们也可以使用它来呈现相同的内容)

此处给出的示例使用的是模板而不是渲染函数,但是幸运的是,还记录了如何在渲染函数中使用作用域插槽:

https://vuejs.org/v2/guide/render-function.html#Slots