【问题标题】:Nesting a slot in a slot for vue将插槽嵌套在 vue 的插槽中
【发布时间】:2019-06-08 23:25:10
【问题描述】:

更新:这是我在这里尝试实现的简化版本(来自下面的线程对话):

接受组件 A - 接受组件 B - 接受一个条件 - 如果 条件为真:用组件 A 包装组件 B [并渲染]- 仅其他 渲染组件 B。

创建一个有条件地呈现包装器的组件感兴趣。我认为像这样的理论方法可能是最好的**:**

<template>
    <div>
        <slot v-if="wrapIf" name="wrapper">
            <slot name="content"></slot>
        </slot>

        <slot v-else name="content"></slot>
    </div>
</template>
<script>
    export default {
        props: {
            wrapIf: Boolean,
        }
    }
</script>

那么当我们实现时,它会看起来是这样的:

...
<wrapper-if :wrap-if="!!link">
    <a :href="link" slot="wrapper"><slot></slot></a>

    <template slot="content">
         content
    </template>
</wrapper-if>

想法是,在这种情况下,如果存在 链接, 那么让我们用包装槽(可以是任何组件)包装内容/element)。 如果没有,那么让我们只渲染内容,而不使用包装的链接。非常简单的逻辑,但我似乎误解了一些基本的 vue 功能,因为 这个特定的例子不起作用。

我的代码有什么问题是否有某种本机 api 已经实现了这个也许是一种依赖这已经是这样了吗?

输出应如下所示:

wrapIf === true

<a href="some.link">
    content
</a>

wrapIf === false

content

【问题讨论】:

    标签: vue.js nested slot


    【解决方案1】:

    只关注内容本身,让组件自己考虑是否封装defaultnamed内容槽。

    如果您需要动态包装器,dynamic component 应该可以解决这个问题。我已经相应地更新了我的解决方案。因此,如果您需要包装器是 label 元素,只需将 tag 属性设置为它,依此类推。

    const WrapperIf = Vue.extend({
      template: `
        <div>
          <component :is="tag" v-if="wrapIf" class="wrapper">
            <slot name="content"></slot>
          </component>
    
          <slot v-else name="content"></slot>
        </div>
      `,
    
      props: ['wrapIf', 'tag']
    });
    
    
    new Vue({
      el: '#app',
    
      data() {
        return {
          link: 'https://stackoverflow.com/company',
    
          tagList: ['p', 'label'],
          tag: 'p',
          wrap: true
        }
      },
    
      components: {
        WrapperIf
      }
    })
    .wrapper {
      display: block;
      padding: 10px;
    }
    
    p.wrapper {
      background-color: lightgray;
    }
    
    label.wrapper {
      background-color: lavender;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    
    <div id="app">
      <wrapper-if :wrap-if="wrap" :tag="tag">
        <a :href="link" slot="content">
           content
        </a>
      </wrapper-if>
    
      <div>
        Change wrapper type:
        <select v-model="tag">
          <option v-for="tag in tagList">{{tag}}</option>
        </select>
      </div>
    
      <button @click="wrap = !wrap">Toggle wrapper</button>
    </div>

    【讨论】:

    • 感谢您的回复,但此解决方案假定静态包装组件/元素。包装器和内容都是任意的。如果我没有说清楚,我很抱歉。我会更新我的答案。
    • 答案已更新。请让我知道这是否解决了您的问题。
    • 尽管wrap === false,这似乎仍然将链接包裹在内容周围
    • @Philll_t 问题是您使用相同的值来设置内容和可见性状态(通过执行!!link),当link 确实包含一个URL 时,它 将呈现包装器,因为您正在强制(布尔转换)来自同一来源的值。这就是为什么为此目的,我在数据内部使用了一个名为 wrap 的单独值。
    • @Philll_t 我相信上述解决方案满足这些条件。让我知道你的想法。
    猜你喜欢
    • 2021-02-06
    • 2019-04-25
    • 2018-08-09
    • 1970-01-01
    • 2018-07-28
    • 2020-05-19
    • 2020-04-29
    • 1970-01-01
    • 2020-03-12
    相关资源
    最近更新 更多