如何封装/包装VueJS组件?

时间:2018-02-15 12:28:02

标签: vue.js vuejs2 vue-component

大家好,请原谅我的英语: - )

我有一个可以使用动态插槽的Vue组件(插槽的名称将取决于道具)。

我在几个地方使用它,一些插槽总是存在。

为了避免冗余,我正在寻找一种方法来创建一个包裹着#34;"最后一个组件,允许我只定义附加插槽。

如果有明显的"实现它的方法,我可能错过了它: - )

代码示例

没有"换行组件"

<b-table
  show-empty
  small
  hover

  [...some others and always present props...]

  :items="aDataVarThatWillChangeBasedOnTheContext"

  [...some others and uniq props...]
>
  <template slot="same-1">
   A slot that will always be present with the same content (for example, a checkbox in the first column)
  </template>

  <template slot="same-2">
   A slot that will always be present with the same content (for example, some action buttons in the last column)
  </template>

  [...some others and always present slots...]

  <template slot="not-the-same">
   A slot that is only used in this context (for example, a duration based on a row timestamp and a timestamp picked by the user)
  </template>

  [...some others and uniq slots...]
</b-table>

使用&#34;换行组件&#34;

<my-b-table
  :items="aDataVarThatWillChangeBasedOnTheContext"
>
  <template slot="not-the-same">
   A slot that is only used in this context (for example, a duration based on a row timestamp and a timestamp picked by the user)
  </template>
</my-b-table>

注意:动态插槽名称不可预测。 如果我突然需要一个&#34; foo&#34;专栏,我应该能够通过&#34; foo&#34;插槽(和#34; HEAD_foo&#34;插槽,在我的情况下)

一些研究

我读了here

  

它们(功能组件)作为包装组件也非常有用。例如,当您需要:

     
      
  • 以编程方式选择要委派的其他几个组件之一
  •   
  • 在将子项,道具或数据传递给子组件之前对其进行操作
  •   

并且&#34;在将儿童,道具或数据传递给儿童组件之前操纵儿童,道具或数据。似乎正是我所需要的。

我查看了渲染功能,但很多事情似乎没有实现,比如v模型,我很难弄清楚如何传递动态插槽......

提前感谢您的回答!

up:在07.03.2018,我仍然不知道如何解决这个案例

2 个答案:

答案 0 :(得分:1)

找到了那个月前我不清楚的答案。

(&#34;动态&#34;表示此处&#34;未由组件明确声明,但由父母提供&#34;)

包装组件

道具和范围广告位可以由options函数的createElement对象动态提供。

&#34;简单&#34;可以通过childs函数的createElement数组动态地给出插槽。

包裹的组件

道具不能是动态的,除非该组件有效。

总是可以动态检索插槽。

只有当组件不起作用时,才能检索范围内的插槽。

结论

不可能同时拥有动态道具和范围插槽......

但是可以宣布所有需要的道具,然后使用&#34;非功能性的&#34;组件作为包装器和包装。

如何

从非功能组件中检索

var component = Vue.component('component-name', {
  props: ['name', 'of', 'the', 'props'],

  // [...]

  aMethod: function () {
    this._props // all the declared props
    this.$slots // all the slots
    this.$scopedSlots // all the scoped slots
  }
});

从功能组件

中检索
var component = Vue.component('component-name', {
  functional: true,

  render: function (createElement, context) {
    context.props // all the props
    context.children // all the slots as an array
    context.slots() // all the slots as an object
  }
});

授予子组件

var component = Vue.component('component-name', {
  render: function (createElement) {
    return createElement(
      childComponent,
      {
        props: propsToGive,
        scopedSlots: scopedSlotsToGive
      },
      [
        // non-scoped slots to give
        createElement('slot-tag-name', {slot: 'slot-name'})
      ]
    );
  }
});

参考

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

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

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

沙盒

https://jsfiddle.net/5umk7p52/

答案 1 :(得分:0)

只需使用自定义的<b-table>制作常规组件。

您需要为您的组件定义items道具作为items组件的<b-table>传递。

而且,要为您的组件定义slot,您需要使用<slot>标记,并使用name属性指定名称。

如果您想在<b-table>组件中访问<my-b-table>组件中的其中一个广告位,只需将<slot>标记作为广告位的内容传递即可你的自定义组件。

它看起来像这样:

Vue.component('my-b-table', {
  template: `
    <b-table
      show-empty
      small
      hover
      :items="items"  
    >
      <template slot="same-1">
        Content to pass to the b-table's slot
      </template>

      <slot name="not-the-same">
        A slot that is only used in this context
      </slot>

      <template slot="last_edit">
        <slot name="last_edit">
          A slot to pass content to the b-table component's slot
        </slot>
      </template>
    </b-table>
  `,
  props: { items: Array },
});