将孩子附加到$ slot.default

时间:2018-05-18 22:53:26

标签: vue.js vuejs2

我有一个组件,我需要在屏幕上显示一些自定义模式。我不知道应该把这个对话框的内容放在哪里,所以我做了类似的事情:

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

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

[...]
  

注意:我无法将[ref=ModalContent]的标记名称设置为template,因为vue会将此标记保留为其他功能。

我的想法是当我点击&#34; show modal&#34;它打开创建了我用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 :(得分:1)

在我看来,这可能是XY problem的情况。

可能发生的情况是您不需要手动填充$slot.default,而是以更标准的方式使用您的Dialog组件。由于在您的问题中没有关于后者的细节,该组件可能还需要一些重构来适应这种“标准方式”。

因此,更标准的方法是直接在父级模板中使用<custom-dialog>组件,而不是使用您必须隐藏的占位符(您引用为ModalContent的占位符)。这样,您在<custom-dialog>内传递的任何HTML都会被输入您的Dialog的{​​{1}}(设计好的广告位)。

这样您还可以省去手动实例化Dialog组件的麻烦。

然后,您可以切换<slot>可见性(使用<custom-dialog>v-if),甚至可以在代码中提及操作DOM中的位置;当v-show是Vue实例时,您可以以$elthis.$refs.ModalContent.$el访问其DOM节点。

您还可以通过将ModalContent方法委托给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>,那么问题评论中的@ Sphinx linked answer是一种可接受的方法。请注意,那里接受的答案也有利于标准用法。在我看来,这也是@Sphinx在第二次评论中暗示的内容。