Вложение слота в слот для Vue - PullRequest
0 голосов
/ 15 января 2019

Обновление: вот упрощенная версия того, чего я пытаюсь достичь здесь (из цепочки обсуждений ниже):

Принять компонент A - Принять компонент B - Принять условие - если условие истинно: обернуть Компонент B Компонентом A [и сделать рендеринг] - иначе компонент рендеринга 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>

Идея состоит в том, что в данном случае , если - это ссылка, , тогда давайте обернем содержимое в слот оболочки (который может быть любым компонентом / элементом) ). Если не , то давайте просто отрендерим содержимое без закрытой ссылки. Довольно простая логика, но, похоже, я неправильно понимаю некоторые базовые функции vue, поскольку этот конкретный пример не работает.

Что не так с моим кодом или , есть ли какой-то нативный API , который уже достигает этой или , возможно зависимости, которая делает это что-то вроде уже?

Вывод должен выглядеть так:

wrapIf === true

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

wrapIf === false

content

1 Ответ

0 голосов
/ 15 января 2019

Просто сфокусируйтесь на самом контенте и позвольте компоненту беспокоиться о том, стоит ли оборачивать по умолчанию или с именем слот контента.

Если вам нужно, чтобы оболочка была динамической, то динамический компонент должен решить эту проблему. Я обновил свое решение соответственно. Поэтому, если вам нужно, чтобы оболочка была элементом 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...