Как использовать дублированные именованные слоты в Vue - PullRequest
0 голосов
/ 28 сентября 2018

Я работаю над упакованным компонентом для v-stepper в Vuetify.В этом случае я хочу, чтобы пользователь определял слот при использовании компонента, а затем я буду использовать это имя слота для построения шагов.

Мне нужно, чтобы этот слот существовал как для рабочего стола, так и длямобильный вид.Я пытался использовать v-if, чтобы скрыть, если мобильный или нет, но это вызвало другие проблемы, поэтому я пошел с v-show, но это дает мне ошибку в консоли разработчика:

Дублированное присутствие слота«page6» находится в том же дереве рендеринга - это, вероятно, приведет к ошибкам рендеринга.

Вот как структурирован компонент Обратите внимание, что они находятся в одном и том же .Vue file

Фрагмент рабочего стола

<v-stepper-items>
    <v-stepper-content v-for="(item,index) in steps" :key="index" :step="index+1">
      <slot :name="item.slot"></slot>
    </v-stepper-content>
  </v-stepper-items>

Мобильный фрагмент

<v-stepper-content :key="`${index}-stepContent-mobile`" :step="index+1">
    <slot :name="item.slot"></slot>
  </v-stepper-content>

Я попытался создать область слота, но, похоже, это не такпримените здесь

<v-stepper-items>
    <v-stepper-content v-for="(item,index) in steps" :key="index" :step="index+1">
      <template :slot-scope="item.slot"><slot :name="item.slot"></slot></template>
    </v-stepper-content>
  </v-stepper-items>

Так пользователь будет настраивать слот при использовании компонента , который можно увидеть здесь

 <div slot="page5">
    <h4>Step 3</h4>
  </div>

Таким образом, ключевым моментом здесь является то, что пользователь устанавливает один слот при использовании компонента, но компонент помещает этот слот в 2 места в файле .vue, один в разделе рабочего стола и один в разделе мобильных устройств.Однако оно должно иметь то же имя, поскольку фактически это тот же слот ...

Вот мой проект github с кодом, вы можете снять его и запустить npm install, а затем npm run dev, чтобыувидеть его в действии: Vuetify-Simple-Wizard

Ответы [ 2 ]

0 голосов
/ 29 сентября 2018

Вы можете использовать Portal-Vue для многоадресной передачи слотов шагов в два местоположения (настольное и мобильное).

Поскольку целевое имя портала может быть динамическим, оно работает при изменении размераокно после первоначального рендеринга, т. е. всякий раз, когда isMobile меняет значение, портал переоценивает и перемещает его содержимое в соответствующий раздел.

<v-stepper v-model="stepStage" :alt-labels="!isMobile" :vertical="isMobile" >
  <div v-show="!isMobile">
    ...
    <v-stepper-items>
      <v-stepper-content v-for="(item,index) in steps" :key="index" :step="index+1">
        <portal-target :name="`portal-desk-${index}`" :key="index" slim></portal-target>
      </v-stepper-content>
    </v-stepper-items>
    ...
  </div>
  <div v-show="isMobile">
    <template v-for="(item,index) in steps">
      ...
      <v-stepper-content :key="`${index}-stepContent-mobile`" :step="index+1">
        <portal-target :name="`portal-mobile-${index}`" :key="index" slim></portal-target>
      </v-stepper-content>
      ...
    </template>
  </div>  

  <template v-for="(item, index) in steps">
    <portal :to="portalName(index)" :key="index">
      <template :slot-scope="item.slot"><slot :name="item.slot"></slot></template>
    </portal>
  </template>

</v-stepper>
computed: {
  portalName() {
    return (index) => {
      const section = this.isMobile ? 'mobile' : 'desk';
      return `portal-${section}-${index}` 
    }
  }
},

v-if

Я не уверен, какие проблемы вы обнаружили с v-if, но, похоже, он работает с v-if на v-stepper-content

<div v-show="!isMobile">
  ...
  <v-stepper-content v-if="!isMobile" v-for="(item,index) in steps" :key="index" :step="index+1">
  ...
<div v-show="isMobile">
  ...
  <v-stepper-content v-if="isMobile" :key="`${index}-stepContent-mobile`" :step="index+1">
0 голосов
/ 28 сентября 2018

Вы можете разбить компонент на SimpleWizardMobile и SimpleWizardDesk , а затем использовать динамический шаблон компонента в SimpleWizard,

template

<template>
  <component :is="deviceType" 
    :completeStep="completeStep" 
    :previousStepLabel="previousStepLabel"
    :nextStepLabel="nextStepLabel"
    :steps="steps"
    :onNext="onNext"
    :onBack="onBack"
    :mobileBreakpoint="mobileBreakpoint"
    :theme="theme"
    ></component>
</template>

компонент

<script>
import SimpleWizardDesk from './SimpleWizardDesk'
import SimpleWizardMobile from './SimpleWizardMobile'
...
computed: {
  deviceType() {
    return this.isMobile ? SimpleWizardMobile : SimpleWizardDesk
  }
},

Я подтвердил, что ваше устройство разработки по-прежнему работает с этой структурой, но не отработал весь рефакторинг js (просто использовал тот жекомпонент для каждого и рефакторинг шаблонов).

...