Добавить дочерний элемент в $ slot.default - PullRequest
0 голосов
/ 19 мая 2018

У меня есть компонент, который мне нужен, чтобы отобразить некоторые пользовательские модальные на экране.Я не знаю, куда мне поместить это диалоговое содержимое, поэтому я сделал что-то вроде этого:

<template>
    <div class="ComponentItself">
        <div v-show="false" ref="ModalContent">
            Hello!
        </div>

        <button v-on:click="showModal">Show modal</button>
    </div>
</template>

[...]

Примечание: Я не смог установить имя тега [ref=ModalContent] to template, потому что vue резервирует этот тег для другой функции.

Моя идея состоит в том, что когда я нажимаю на "show modal", он открывает, создает экземпляр другого компонента (v-dialog), который ясоздали с содержимым [ref=ModalContent] (его следует скомпилировать для поддержки вложенных компонентов vue).

import Dialog from './Dialog';

const DialogCtor = Vue.extend(Dialog);
const dialog = new DialogCtor({ propsData: {...} });

dialog['$slots'].default = [ this.$refs['templateNewFolder'].innerHTML ];

{something like document.body.appendChild(dialog.$el)}

Этот другой компонент имеет слот, который может принимать содержимое HTML, отображаемое внутри него.И это просто не работает.Отображается модальное содержимое, но содержимое слота равно undefined или содержимое HTML не проанализировано.

<div class="Dialog">
    [...]
    <slot></slot>       
    [...]
</div>

Текущий результат выглядит примерно так:

enter image description here enter image description here


Что мне нужно:

  • Мне нужно знать, нахожусь ли я на правильном пути.У меня есть функция component, но я не смог определить или понять, может ли она решить мою проблему;
  • Что я могу сделать, чтобы она заработала;
  • Некоторые подобные проекты могли быпомогите, но я не смог никого найти;
  • Может быть, я мог бы решить мою проблему, если это возможно, я просто .appendChild() прямо на $slot.default, но это невозможно;

1 Ответ

0 голосов
/ 19 мая 2018

Мне кажется, что это может быть проблемой XY .

Что, вероятно, случается, что вам не нужно вручную заполнять $slot.default, но используйте ваш Dialog компонент более стандартным способом.Поскольку в последнем вопросе есть немного подробностей о последнем, этому компоненту также может потребоваться некоторый рефакторинг, чтобы соответствовать этому «стандартному способу».

Так что более стандартным подходом было бы непосредственное использование компонента <custom-dialog> вшаблон вашего родителя, вместо использования заполнителя (тот, на который вы ссылаетесь ModalContent), который вы должны скрыть.Таким образом, какой бы HTML-код вы ни передавали в этом <custom-dialog>, он будет подаваться в Dialog <slot> (разработанный слот слота).

Таким образом, вы также избавите себя от необходимости вручную создавать экземплярваш компонент Dialog.

Затем вы можете переключать свою <custom-dialog> видимость (с помощью v-if или v-show) или даже манипулировать ее положением в DOM, как вы упоминаете в своем коде;вы можете получить доступ к его узлу DOM как $el: this.$refs.ModalContent.$el, когда ModalContent является экземпляром Vue.

Вы также можете разложить метод showModal, делегировав его компоненту Dialog.

Пример кода:

Vue.component('modal-dialog', {
  template: '#modal-dialog',
  data() {
    return {
      modalShown: false,
    };
  },
  methods: {
    showModal() {
      this.modalShown = true;
    },
    hideModal() {
      this.modalShown = false;
    },
  },
});

new Vue({
  el: '#app',
  methods: {
    showModal() {
      this.$refs.ModalContent.showModal();
    },
  },
});
/*
https://sabe.io/tutorials/how-to-create-modal-popup-box
MIT License https://sabe.io/terms#Licensing
*/

.modal {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  opacity: 0;
  visibility: hidden;
  transform: scale(1.1);
  transition: visibility 0s linear 0.25s, opacity 0.25s 0s, transform 0.25s;
}

.modal-content {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: white;
  padding: 1rem 1.5rem;
  width: 24rem;
  border-radius: 0.5rem;
}

.close-button {
  float: right;
  width: 1.5rem;
  line-height: 1.5rem;
  text-align: center;
  cursor: pointer;
  border-radius: 0.25rem;
  background-color: lightgray;
}

.close-button:hover {
  background-color: darkgray;
}

.show-modal {
  opacity: 1;
  visibility: visible;
  transform: scale(1.0);
  transition: visibility 0s linear 0s, opacity 0.25s 0s, transform 0.25s;
}
<script src="https://unpkg.com/vue/dist/vue.js"></script>

<div id="app">
  <modal-dialog ref="ModalContent">
    Hello!
  </modal-dialog>
  <h1>Hello World</h1>
  <button v-on:click="showModal">Show modal</button>
</div>

<template id="modal-dialog">
<div class="modal" :class="{'show-modal': modalShown}" @click="hideModal">
  <div class="modal-content">
    <span class="close-button" ref="closeButton" @click="hideModal">&times;</span>
    <slot></slot>
  </div>
</div>
</template>

Теперь, если вы действительно хотите поиграться с $slot, связным ответом @ Sphinx inкомментарии к вопросу - приемлемый подход.Обратите внимание, что принятый ответ также способствует стандартному использованию.Мне кажется, что это также то, что @Sphinx подразумевает во втором комментарии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...