【问题标题】:Vue 2.0 Component - could not render all <div>s within a templateVue 2.0 组件 - 无法呈现模板中的所有 <div>
【发布时间】:2017-03-16 15:05:30
【问题描述】:

我在学习 VueJS 时正在编写一个模态组件。 modal 组件基本上由两个主要元素组成:包含所有内容的实际框和叠加层。

现在我遇到的问题是覆盖元素根本没有渲染。但是如果我将覆盖从组件模板移动到父范围,一切都会好起来的。

这里是父作用域的代码:

<my-modal v-show="show" v-on:hide="show = false"></my-modal>
<!-- Overlay will be rendered properly if I put overlay here. -->
<!-- <div class="my-modal-overlay" v-show="show" @click="show = false"></div>  -->

以及组件模板的代码:

<template id="tpl-my-modal">
    <transition name="modal-fade" enter-active-class="animated zoomIn" leave-active-class="animated zoomOut">
            <div class="my-modal-box">
                <div class="my-modal-content">
                    <div class="my-modal-header"><h1>Title</h1></div>
                    <div class="my-modal-body">Body</div>
                    <div class="my-modal-footer"><button class="btn btn-danger" @click="$emit('hide')">Close</button></div>
                </div>
            </div>
            <!-- Overlay is not rendered at all if I put it here. -->
            <div class="my-modal-overlay" @click="show = false"></div>
        </transition>
    </template>

Javascript:

Vue.component('my-modal', {
    template: '#tpl-my-modal'
})

两张截图。灰色层是覆盖所有视口的覆盖元素。

谁能解释一下这个问题?谢谢!


更新:

snippets 来了。随意评论/注释掉 HTML 中的第 11 行/第 26 行,看看有什么不同。


更新:

原来一个Vue Component不能有超过一个根元素,而&lt;transition&gt;标签只能有一个元素,也就是说我之前的做法是错误的。

因此我稍微调整了代码,现在在控制台中 Vue 不再抱怨了。并且模态框和叠加层都被渲染了。

<template id="tpl-my-modal">
    <div>
      <transition name="modal-fade" enter-active-class="animated zoomIn" leave-active-class="animated zoomOut">
        <div class="my-modal-box">
          <div class="my-modal-content">
            <div class="my-modal-header">
              <h1>{{ program.title }}</h1></div>
            <div class="my-modal-body"> {{ program.intro }}</div>
            <div class="my-modal-footer">
              <button class="btn btn-danger" @click="$emit('hide')">Close</button>
            </div>
          </div>
        </div>
      </transition>
      <div class="my-modal-overlay" @click="show = false"></div>
    </div>
  </template>

但是有一个问题没有解决:所有的转换都消失了。这是snippets。有什么问题?

【问题讨论】:

  • 我认为如果叠加层出现在父组件中是有道理的,你可以做的是当模式打开时,你用你的叠加层在父组件上切换一个类。
  • @flyingSmurfs 我认为父组件并不真正关心模态组件内部的内容。想想可重用性:如果有 100 个父组件要使用这个模态组件,他们必须在自己的模板中定义一个叠加层(作为程序员,我们必须复制和粘贴 100 次),这绝对不是很酷,对吧?这就是为什么我最初将它放在子组件模板中的原因。但不知何故,Vue 只是不渲染覆盖层。
  • 将模型 div 和覆盖 div 包裹在另一个 div 中 jsfiddle.
  • @ABDEL-RHMAN 谢谢。但是如果你包装模态框并覆盖,行为/动画会变得有点奇怪,不是吗?不太可能是用户所期望的,对吧?大声笑。

标签: vue.js vue-component


【解决方案1】:

检查这个小提琴https://jsfiddle.net/cihkem/0rmt28y2/

Vue.component('my-modal', {
  template: '#tpl-my-modal',
  props: ['program', 'show']
})

new Vue({
  el: '#app',
  data: {
    show: false,
    activeProgram: {},
    programs: [{
      title: 'Westworld',
      intro: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eligendi cum incidunt ipsum impedit nostrum, repellendus illum, officia labore neque ea quam ad maiores corporis deserunt quos odio distinctio similique in.'
    }, {
      title: 'Game of Thrones',
      intro: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eveniet perspiciatis eos aperiam, veritatis, voluptate eius similique saepe libero consectetur suscipit dolorem molestiae animi nostrum voluptatem quidem sapiente? Fugit, hic, fugiat!'
    }, {
      title: 'X Files',
      intro: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugit nobis, nisi ex exercitationem magnam nemo repudiandae dolor maxime odio reprehenderit animi ducimus a consequatur, saepe suscipit dolorem ratione tempore perferendis.'
    }]
  },
  methods: {
    showDetails: function(program) {
      this.show = true;
      this.activeProgram = program;
    }
  }
})
.my-modal-overlay {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1040;
  background-color: #000;
  opacity: .3;
}

.my-modal-box {
  opacity: 1;
  position: relative;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1050;
}

.my-modal-content {
  background-color: #fff;
  position: relative;
  height: auto;
  width: 600px;
  margin: 30px auto;
  padding: 10px;
  z-index: 1050;
}

.my-modal-header {
  text-align: center;
}

.my-modal-body,
.my-modal-footer {
  padding: 10px 0;
}

.my-modal-header,
.my-modal-body {
  border-bottom: 1px solid #d0d0d0;
}

.my-modal-footer {
  text-align: right;
}

.program-list-item {
  padding: 3px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script>
<body>
  <div class="container">
    <div id="app">
      <ol>
        <li v-for="program in programs" class="program-list-item">
          {{ program.title}}
          <button class="btn btn-primary btn-sm" @click="showDetails(program)">Details</button>
        </li>
      </ol>
      <my-modal :show="show" v-on:hide="show = false" v-bind:program="activeProgram"></my-modal>
      <!--  <div class="my-modal-overlay" v-show="show" @click="show = false"></div> -->
    </div>
  </div>
  <template id="tpl-my-modal">
    <div>
      <transition enter-active-class="animated zoomIn" leave-active-class="animated zoomOut">
        <div v-show="show" class="my-modal-box" key="modal">
          <div class="my-modal-content">
            <div class="my-modal-header">
              <h1>{{ program.title }}</h1></div>
            <div class="my-modal-body"> {{ program.intro }}</div>
            <div class="my-modal-footer">
              <button class="btn btn-danger" @click="$emit('hide')">Close</button>
            </div>
          </div>
        </div>         
      </transition>     
      <div v-show="show" class="my-modal-overlay" @click="show = false" key="overlay"></div>
    </div>
  </template>
</body>

这是你需要的吗?

【讨论】:

    【解决方案2】:

    对于转换问题,您应该像这样将transition 标记放在模板的根div 之后..

    <template id="tpl-my-modal">
    <transition name="modal-fade" enter-active-class="animated zoomIn" leave-active-class="animated zoomOut">
        <div>
        //the rest of your code..
    

    因为v-show在你使用组件my-modal时会被应用到根div

    <my-modal v-show="show" v-on:hide="show = false" v-bind:program="activeProgram"></my-modal>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-28
      • 2018-06-04
      • 2021-05-04
      • 2017-02-25
      • 2017-08-28
      • 2019-04-01
      • 2017-06-10
      • 1970-01-01
      相关资源
      最近更新 更多