【问题标题】:Truly Nested Components in Vue.js?Vue.js 中真正的嵌套组件?
【发布时间】:2016-07-21 21:52:03
【问题描述】:

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

示例:假设我正在构建一个 'accordion' 元素。 Accordions 由 'heading''content' 部分组成。通过单击标题可以将内容切换进出视图。像这样的元素的最终 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>

'heading' 和 'content' 元素不是通用的,应该只存在于父 'accordion' 元素的上下文中,所以我认为它们应该在父组件的定义中声明 .

我知道为了捕获一个元素的innerHTML内容,我们必须使用&lt;slot&gt;元素,所以我尝试使用以下模板:

<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'
});

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

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

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

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

【问题讨论】:

    标签: javascript components custom-component vue.js


    【解决方案1】:

    所以&lt;heading&gt;&lt;content&gt; 也应该是 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'
        }
      }
    })
    

    所以:

    • &lt;heading&gt; 元素的内容进入 &lt;heading&gt; 的模板。
    • &lt;heading&gt;的整个模板进入&lt;slot name="heading"&gt;inside &lt;accordion&gt;的模板

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

    【讨论】:

    • 感谢您的建议。 Vue 的GitHub Issue Tracker 中有一个关于这个问题的长时间讨论。您的解决方法是可用的,但破坏了标题和内容元素的模块化,并产生了不必要的复杂和令人费解的 html - 如问题跟踪器中的讨论所述 - 这并不理想。希望这次讨论能够解决这个问题,这样在 Vue 中构建更复杂的嵌套元素会变得更容易。
    猜你喜欢
    • 2015-11-22
    • 2018-03-22
    • 1970-01-01
    • 2018-11-06
    • 2019-07-08
    • 1970-01-01
    • 2018-05-22
    • 2021-01-02
    • 2019-02-11
    相关资源
    最近更新 更多