vue.js将组件安装到应用程序根目录

时间:2018-07-17 22:12:41

标签: vue.js vuejs2

我有一个modal.vue组件,如下所示:

<template>

    <transition name="modal-transition">
        <div class="modal-body" v-if="displayed">
            <div class="modal-overlay" @click="displayed = false"></div>
            <div class="modal-content">
                <slot/>
            </div>
        </div>
    </transition>

</template>

如何将这个组件安装到应用程序的根元素而不是就位?

对于不精确的示例:

<body>
  <div id="app">
    <div class="header"></div>
    <div class="nav"></div>
    <div class="stage">
       <div class="sub-nav"></div>
       <div class="content">
          <modal :display.sync="display">MY MODAL</modal> <-- Don't mount here...
       </div>
    </div>
    <-- Mount here instead...
  </div>
</body>

当前问题是我的网站标题和导航位于我的模式顶部,并且它的全屏覆盖层变暗了,而不是模式覆盖层的后面。

Header and Navigation on top

2 个答案:

答案 0 :(得分:2)

将元素自身的元素移动到应用程序根目录的元素可以通过两种方式来实现:使用门户作为首选解决方案或使用附加。

使用门户网站(首选方法)

  

PortalVue是一组两个组件,可让您呈现一个   组件模板(或其一部分)在文档中的任何位置,甚至   在您的Vue应用程序控制的部分之外!

https://linusborg.github.io/portal-vue/#/


使用追加(不是最佳做法)

如果添加门户网站库太繁琐,则允许使用附加,但在VUE文档中正式建议不要这样做。

通常,此特定的安装位置将满足您需要呈现在整个应用程序顶部的模态或对话框弹出窗口的z-index覆盖。在此示例中,您始终可以使用标准的 getElementBy querySelector 函数将 this。$ root。$ el 替换为其他元素目标。

在不移动和重新添加元素的情况下,所有响应功能将保持不变。

<script>

    export default {

        name: 'modal',

        ...

        mounted: function() {
            this.$root.$el.append(this.$el);
        },

        destroyed: function() {
            this.$el.parentNode.removeChild(this.$el);
        }
    }
</script>

已安装时,该元素将移动到顶级VUE应用程序实例的安装位置。

已销毁上,从新的父级中删除了已迁移组件的占位符DOM注释,以防止每次组件重新安装其自身时发生孤立的重复。 VUE正式声明不要销毁VUE之外的元素,因此请勿将此与该声明相混淆,此处组件已被销毁。

例如,当使用vue-router切换视图时,通常会发生这种DOM注释重复,因为这种机制每次vue-router视图状态更改时都会安装和卸载路由器视图中的所有组件。

此行为是由vue-router引起的错误,该对象已被VUE渲染管理器正确销毁,但仍然错误地保留了索引引用,使用门户网站软件包可以解决此问题。

这是结果:

Header and Navigation underneath!

答案 1 :(得分:2)

Vue 3 的更新

现在有一个名为 teleport 的内置功能,它允许将组件模板的一部分安装到任何 DOM 元素。

来自 OP 的示例看起来像这样

<!-- MyModal.vue -->
<template>
    <transition name="modal-transition">
        <div class="modal-body" v-if="displayed">
            <div class="modal-overlay" @click="displayed = false"></div>
            <div class="modal-content">
                <slot/>
            </div>
        </div>
    </transition>
</template>
<!-- SomeDeeplyNestedComponent.vue -->
<template>
    <teleport to="#app">
        <!-- Can still receive props from parent -->
        <MyModal :my-prop="foo">
           <!-- slot content -->
        </MyModal>
    </teleport>
</template>