在我的插槽中包装动态添加的子元素

问题描述

如果我有一个只有一个插槽的组件,而不是仅仅渲染它的所有子元素,我想包装每个元素,我会做这样的事情:

Vue.component('MyElement',{
  render: function(createElement){
      for (let i = 0; i < this.$slots.default.length; i++) {
      //create a wrapper element
      let wrappedElement = createElement("div",{},this.$slots.default[i]);
      // replace the current element in this slot,with the wrapped element
      this.$slots.default[i] = wrappedElement;
    }

    return createElement("div",this.$slots.default);
  }
}

像这样使用:

<MyElement ref="myElement">
  <p>Item 1</p>
  <p>Item 2</p>
</MyElement>

最终看起来像这样

<div>
  <div>
    <p>Item 1</p>
  </div>
  <div>
     <p>Item 2</p>
  </div>
</div>

到目前为止一切都很好。

现在,当我想使用

将另一个 <p> 元素插入到 <MyElement> 中时
// get reference to <MyElement>
const myElement = this.$refs["myElement"];
// create a new element
var newElement = document.createElement("div");
newElement.innerText = "Hiya";
myElement .$el.appendChild(newElement);

新元素不会被包装,因为不会再次调用渲染,我如何完全控制插槽中每个子元素的渲染?或者是否有更好的时间以编程方式将子项附加到组件中?

谢谢

解决方法

如果您可以考虑为项目创建一个 component。因此,当您想要添加新项目时,您只需创建一个 method 来调用项目组件。

我为此示例制作了一个代码片段。

Vue.component('MyElement',{
  template: '#element-container',});

Vue.component('MyElementItem',{
  template: '#element-item',props: {
    innerText: {
      type: String,default: '',}
  }
});

new Vue({
  el: '#app',data() {
    return {
      items: ['Item 1','Item 2','Item 3'],}
  },method: {
    // you can add a method that will add more items,then the MyElementItem component will be invoked.
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <my-element>
    <my-element-item v-for="(item,index) in items" :key="index" :inner-text="item" />
  </my-element>
</div>

<script type="text/x-template" id="element-container">
  <div>
    <slot></slot>
  </div>
</script>

<script type="text/x-template" id="element-item">
  <div>
    <p>{{ innerText }}</p>
  </div>
</script>