Vue.js中的真正嵌套组件?

时间:2016-04-01 23:25:45

标签: javascript components custom-component vue.js

是否可以使用Vue.js创建语义嵌套元素?

示例:让我们说我正在构建'手风琴' 元素。手风琴由'标题' '内容' 部分组成。通过单击标题可以切换内容和视图内容。像这样的元素的最终html将是这样的:

<div class="accordion">
    <div class="heading">
        My Accordion
    </div>
    <div class="content">
        Accordions are fun! Loren ipsum dolor sit amet.
        This can be extensive text, include pictures, etc.
    </div>
</div>

我希望能够使用如下语法在我的html中创建这样的元素:

<accordion>
    <heading>My Accordion</heading>
    <content>
        Accordions are fun! Loren ipsum dolor sit amet.
        This can be extensive text, include pictures, etc.
    </content>
</accordion>

&#39;标题&#39;和&#39;内容&#39;元素不是通用的,只应存在于父母手风琴的背景下。元素,所以我认为它们应该在的父组件定义中声明

我知道为了捕获元素的innerHTML内容,我们必须使用<slot>元素,所以我尝试使用以下模板:

<template id="heading">
    <div class="heading">
        <slot></slot>
    </div>
</template>

<template id="content">
    <div class="content">
        <slot></slot>
    </div>
</template>

<template id="accordion">
    <div class="accordion">
        <heading></heading>
        <content></content>
    </div>
</template>

<div id="app">

    <accordion>
        <heading>My Accordion</heading>
        <content>
           Accordions are fun. Lorem ipsum dolor sit amet.
           I could add a lot more text here, or other elements.
        </content>
     </accordion>

</div>

和Vue javascript ...:

Vue.component('accordion', {
    template: '#accordion',
    components: {
        heading: {
            template: '#heading'
        },
        content: [
            template: '#content'
        }
    }
});

Vue({
    el: '#app'
});

不幸的是,它不起作用。我已多次阅读官方文档,并且在&#39; Components&#39; 部分中,当它讨论<slot>元素时,它似乎表明我们应该能够做到 - 但我不能为我的生活弄清楚如何...文档实际上提到了一个具有这样结构的元素:

<app>
    <app-header></app-header>
    <app-footer></app-footer>
</app>

......但它没有给出如何做的简单,具体的例子。

信息从父元素传递到子元素的方式令人困惑,我无法在线找到任何教程如何设置这样的嵌套元素。任何指导都将不胜感激。

1 个答案:

答案 0 :(得分:0)

所以<heading><content>也应该是Vue组件吗?

那么它应该是这样的:

<div id="app">
  <h5>Accordion test</h5>
  <accordion>
    <heading slot="heading">Heading Text</heading>
    <content slot="content">Content Text</content>
  </accordion>

<template id="accordion">
  <div class="header">
    <slot name="heading"></slot>
  </div>
  <div class="content">
    <slot name="content"></slot>
  </div>
</template>

<template id="heading">
  <div class="template-heading">
    <slot></slot>
  </div>
</template>

<template id="content">
  <div class="template-content">
    <slot></slot>
  </div>
</template>
</div>

和JS:

var Heading = Vue.extend({
  template: '#heading'
})
var Content = Vue.extend({
  template: '#content'
})
var Accordion = Vue.extend({
  template: '#accordion',
  components: {
    heading: Heading,
    content: Content
  }
})
Vue.component('heading', Heading)
Vue.component('content', Content)
Vue.component('accordion', Accordion)

var App = new Vue({
  el: '#app',
  data() {
    return {
        test: 'Test'
    }
  }
})

所以:

  • <heading>元素的内容进入内部的插槽 <heading>的模板。
  • <heading>的整个模板进入<slot name="heading">
  • 模板内的<accordion>

工作小提琴:https://jsfiddle.net/Linusborg/ud9a614o/