如何以编程方式创建Vue.js插槽?

时间:2018-05-03 08:44:30

标签: javascript vue.js vuejs2 vue-component

我有一个带插槽的以下组件:

<template>
    <div>
        <h2>{{ someProp }}</h2>
        <slot></slot>
    </div>
</template>

由于某些原因,我必须手动实例化此组件。我就是这样做的:

const Constr = Vue.extend(MyComponent);
const instance = new Constr({
    propsData: { someProp: 'My Heading' }
}).$mount(body);

问题是:我无法以编程方式创建插槽内容。到目前为止,我可以创建基于字符串的简单插槽:

const Constr = Vue.extend(MyComponent);
const instance = new Constr({
    propsData: { someProp: 'My Heading' }
});

// Creating simple slot
instance.$slots.default = ['Hello'];

instance.$mount(body);

问题是 - 如何以编程方式创建$slots并将其传递给我使用new创建的实例?

注意:我没有使用完整版本的Vue.js(仅限运行时)。所以我没有Vue.js编译器可以动态编译模板。

4 个答案:

答案 0 :(得分:5)

我查看了Vue.js的TypeScript定义文件,并在Vue组件实例上找到了一个未记录的函数:$createElement()。我的猜测是,它是传递给组件的render(createElement)函数的相同函数。所以,我能够解决它:

const Constr = Vue.extend(MyComponent);
const instance = new Constr({
    propsData: { someProp: 'My Heading' }
});

// Creating simple slot
const node = instance.$createElement('div', ['Hello']);
instance.$slots.default = [node];

instance.$mount(body);

但这显然没有记载,因此有问题的方法。如果有更好的方法,我不会给它回答。

答案 1 :(得分:2)

我想我终于迷失了以编程方式创建slot元素的方法。据我所知,这种方法似乎不适用于功能组件。我不确定为什么。

如果要为组件实现自己的render方法,则可以使用createElement方法(或在render方法中别名的任何对象)以编程方式创建要传递给子元素的插槽,并传递可以包括{插槽:NAME_OF_YOUR_SLOT},后跟该插槽中的所有子项。

例如:

Vue.config.productionTip = false
Vue.config.devtools = false;

Vue.component('parent', {
  render (createElement) {
    return createElement('child', [
      createElement('h1', { slot: 'parent-slot' }, 'Parent-provided Named Slot'),
      createElement('h2', { slot: 'default' }, 'Parent-provided Default Slot')
    ])
  }
})

Vue.component('child', {
  template: '<div><slot name="parent-slot" /><slot /></div>'
})

new Vue({
  el: '#app',
  template: '<parent />'
})
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>

<div id='app'>
</div>

答案 2 :(得分:1)

(这并没有真正回答How to create Vue.js slot programatically?。但它确实解决了您的问题。)

与使用$createElement()相比,这种技巧不那么苛刻。

基本上,创建一个将MyComponent注册为本地组件的新组件。

const Constr = Vue.extend({
  template: `
  <MyComponent someProp="My Heading">
    <div>slot here !!!</div>
  </MyComponent>
  `,
  components: {
    MyComponent: MyComponent
  }
});
const instance = new Constr().$mount('#app');

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

答案 3 :(得分:0)

我刚刚在vue论坛上遇到了一个答案: slots

原理是:没有什么比createElement('slot'..) 相反,有一个提供 slotted innerHtml作为功能的渲染函数: $ scopedSlots.default()

用法:

render: function (createElement) {
  const self = this;
  return createElement("div", this.$scopedSlots.default());
}

如果要提供默认值以防插槽中没有内容,则需要自己编写区分代码并渲染其他内容。 (上面的链接提供了更详细的示例)

该函数返回一个数组,因此不能用作渲染函数的根。在上面的示例中,需要将其包装到单个容器节点中,例如 div