为什么带有 v-if 的元素内部的过渡没有进入过渡但离开有效?
Why is transition inside an element with v-if not entering the transition but leaving works?
标题几乎说明了一切。我在 Whosebug 上搜索了解决方案,但 他们提供了帮助。
使用经典模态组件的示例:
Vue.component('modal', {
template: `
<transition name="modal">
<div class="modal-wrapper">
<div class="modal-dialog">
<slot></slot>
</div>
</div>
</transition>
`,
})
const app = new Vue({
el: '#app',
data: {
showModal: false,
},
})
/* transition */
.modal-enter-active,
.modal-leave-active {
transition: opacity .5s;
}
.modal-enter,
.modal-leave-to {
opacity: 0;
}
.modal-wrapper {
position: absolute;
left: 0; right: 0;
top: 0; bottom: 0;
display: flex;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, .25);
}
.modal-dialog {
max-width: 90%;
padding: 1em;
background: white;
}
<script src="https://vuejs.org/js/vue.js"></script>
<div id="app">
<p><button @click="showModal = true">Show modal</button></p>
<modal v-if="showModal">
<h3>Hello world</h3>
<p>Amet quam alias amet incidunt voluptatum sapiente Mollitia</p>
<p><button @click="showModal = false">Close</button></p>
</modal>
</div>
(控制台也没有报错)
然而,使用v-show
时一切正常。但是我不能在我的项目中真正使用它来代替 v-if。
Vue.component('modal', {
template: `
<transition name="modal">
<div class="modal-wrapper">
<div class="modal-dialog">
<slot></slot>
</div>
</div>
</transition>
`,
})
const app = new Vue({
el: '#app',
data: {
showModal: false,
},
})
/* transition */
.modal-enter-active,
.modal-leave-active {
transition: opacity .5s;
}
.modal-enter,
.modal-leave-to {
opacity: 0;
}
.modal-wrapper {
position: absolute;
left: 0; right: 0;
top: 0; bottom: 0;
display: flex;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, .25);
}
.modal-dialog {
max-width: 90%;
padding: 1em;
background: white;
}
<script src="https://vuejs.org/js/vue.js"></script>
<div id="app">
<p><button @click="showModal = true">Show modal</button></p>
<modal v-show="showModal">
<h3>Hello world</h3>
<p>Amet quam alias amet incidunt voluptatum sapiente Mollitia</p>
<p><button @click="showModal = false">Close</button></p>
</modal>
</div>
就是说,我必须在 使用 的任何地方用 <transition>
包裹 <modal>
并从模态本身移除过渡(这不会听起来不错)
<transition name="modal">
<modal>
...
</modal>
</transition>
为什么会这样以及如何使进入动画工作(使用 v-if
和 <transition>
在 模态组件中?
我注意到 Vue 2.5(而不是 Vue 2.6)没有这样的问题。从那时起肯定发生了一些变化。
那是因为 v-if inserts/destroys 元素和 v-show 隐藏了它们(不从 DOM 中删除它们)。在您的示例中,如果 v-if
是设置 on/above 过渡元素,则 transition
不存在。如果您将 v-if
移动到转换下方,那么它将起作用。
Vue.component('modal', {
props: ['showModal'],
template: `
<transition name="modal">
<div class="modal-wrapper" v-if="showModal">
<div class="modal-dialog">
<slot></slot>
</div>
</div>
</transition>
`,
})
const app = new Vue({
el: '#app',
data: {
showModal: false,
},
})
/* transition */
.modal-enter-active,
.modal-leave-active {
transition: opacity .5s;
}
.modal-enter,
.modal-leave-to {
opacity: 0;
}
.modal-wrapper {
position: absolute;
left: 0; right: 0;
top: 0; bottom: 0;
display: flex;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, .25);
}
.modal-dialog {
max-width: 90%;
padding: 1em;
background: white;
}
<script src="https://vuejs.org/js/vue.js"></script>
<div id="app">
<p><button @click="showModal = true">Show modal</button></p>
<modal :show-modal="showModal">
<h3>Hello world</h3>
<p>Amet quam alias amet incidunt voluptatum sapiente Mollitia</p>
<p><button @click="showModal = false">Close</button></p>
</modal>
</div>
您缺少 appear
属性。
默认情况下,第一次插入元素时,Vue 不会设置动画。根据文档:
If you also want to apply a transition on the initial render of a node, you can add the appear attribute:
<transition appear>
<!-- ... -->
</transition>
By default, this will use the transitions specified for entering and leaving. If you’d like however, you can also specify custom CSS classes:
<transition
appear
appear-class="custom-appear-class"
appear-to-class="custom-appear-to-class"
appear-active-class="custom-appear-active-class"
>
<!-- ... -->
</transition>
因此只需添加 appear
即可解决问题。
这应该可以解决问题:
{
template: `
<transition name="modal">
<div v-if="show">...</div>
</transition>
`,
data() {return {
show: false,
}},
mounted() {
this.show = true
},
}
我认为这种方法(我相信它确实如此)将动画延迟 1 个 Vue tick,并且大量嵌套此类动画元素会明显减慢速度。
Vue.component('modal', {
template: `
<transition name="modal">
<div class="modal-wrapper" v-if="show">
<div class="modal-dialog">
<slot></slot>
</div>
</div>
</transition>
`,
data() {return {
show: false,
}},
mounted() {
this.show = true
}
})
const app = new Vue({
el: '#app',
data: {
showModal: false,
},
})
/* transition */
.modal-enter-active,
.modal-leave-active {
transition: opacity .5s;
}
.modal-enter,
.modal-leave-to {
opacity: 0;
}
.modal-wrapper {
position: absolute;
left: 0; right: 0;
top: 0; bottom: 0;
display: flex;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, .25);
}
.modal-dialog {
max-width: 90%;
padding: 1em;
background: white;
}
<script src="https://vuejs.org/js/vue.js"></script>
<div id="app">
<p><button @click="showModal = true">Show modal</button></p>
<modal v-if="showModal">
<h3>Hello world</h3>
<p>Amet quam alias amet incidunt voluptatum sapiente Mollitia</p>
<p><button @click="showModal = false">Close</button></p>
</modal>
</div>
标题几乎说明了一切。我在 Whosebug 上搜索了解决方案,但
使用经典模态组件的示例:
Vue.component('modal', {
template: `
<transition name="modal">
<div class="modal-wrapper">
<div class="modal-dialog">
<slot></slot>
</div>
</div>
</transition>
`,
})
const app = new Vue({
el: '#app',
data: {
showModal: false,
},
})
/* transition */
.modal-enter-active,
.modal-leave-active {
transition: opacity .5s;
}
.modal-enter,
.modal-leave-to {
opacity: 0;
}
.modal-wrapper {
position: absolute;
left: 0; right: 0;
top: 0; bottom: 0;
display: flex;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, .25);
}
.modal-dialog {
max-width: 90%;
padding: 1em;
background: white;
}
<script src="https://vuejs.org/js/vue.js"></script>
<div id="app">
<p><button @click="showModal = true">Show modal</button></p>
<modal v-if="showModal">
<h3>Hello world</h3>
<p>Amet quam alias amet incidunt voluptatum sapiente Mollitia</p>
<p><button @click="showModal = false">Close</button></p>
</modal>
</div>
(控制台也没有报错)
然而,使用v-show
时一切正常。但是我不能在我的项目中真正使用它来代替 v-if。
Vue.component('modal', {
template: `
<transition name="modal">
<div class="modal-wrapper">
<div class="modal-dialog">
<slot></slot>
</div>
</div>
</transition>
`,
})
const app = new Vue({
el: '#app',
data: {
showModal: false,
},
})
/* transition */
.modal-enter-active,
.modal-leave-active {
transition: opacity .5s;
}
.modal-enter,
.modal-leave-to {
opacity: 0;
}
.modal-wrapper {
position: absolute;
left: 0; right: 0;
top: 0; bottom: 0;
display: flex;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, .25);
}
.modal-dialog {
max-width: 90%;
padding: 1em;
background: white;
}
<script src="https://vuejs.org/js/vue.js"></script>
<div id="app">
<p><button @click="showModal = true">Show modal</button></p>
<modal v-show="showModal">
<h3>Hello world</h3>
<p>Amet quam alias amet incidunt voluptatum sapiente Mollitia</p>
<p><button @click="showModal = false">Close</button></p>
</modal>
</div>
就是说,我必须在 使用 的任何地方用 <transition>
包裹 <modal>
并从模态本身移除过渡(这不会听起来不错)
<transition name="modal">
<modal>
...
</modal>
</transition>
为什么会这样以及如何使进入动画工作(使用 v-if
和 <transition>
在 模态组件中?
我注意到 Vue 2.5(而不是 Vue 2.6)没有这样的问题。从那时起肯定发生了一些变化。
那是因为 v-if inserts/destroys 元素和 v-show 隐藏了它们(不从 DOM 中删除它们)。在您的示例中,如果 v-if
是设置 on/above 过渡元素,则 transition
不存在。如果您将 v-if
移动到转换下方,那么它将起作用。
Vue.component('modal', {
props: ['showModal'],
template: `
<transition name="modal">
<div class="modal-wrapper" v-if="showModal">
<div class="modal-dialog">
<slot></slot>
</div>
</div>
</transition>
`,
})
const app = new Vue({
el: '#app',
data: {
showModal: false,
},
})
/* transition */
.modal-enter-active,
.modal-leave-active {
transition: opacity .5s;
}
.modal-enter,
.modal-leave-to {
opacity: 0;
}
.modal-wrapper {
position: absolute;
left: 0; right: 0;
top: 0; bottom: 0;
display: flex;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, .25);
}
.modal-dialog {
max-width: 90%;
padding: 1em;
background: white;
}
<script src="https://vuejs.org/js/vue.js"></script>
<div id="app">
<p><button @click="showModal = true">Show modal</button></p>
<modal :show-modal="showModal">
<h3>Hello world</h3>
<p>Amet quam alias amet incidunt voluptatum sapiente Mollitia</p>
<p><button @click="showModal = false">Close</button></p>
</modal>
</div>
您缺少 appear
属性。
默认情况下,第一次插入元素时,Vue 不会设置动画。根据文档:
If you also want to apply a transition on the initial render of a node, you can add the appear attribute:
<transition appear> <!-- ... --> </transition>
By default, this will use the transitions specified for entering and leaving. If you’d like however, you can also specify custom CSS classes:
<transition appear appear-class="custom-appear-class" appear-to-class="custom-appear-to-class" appear-active-class="custom-appear-active-class" > <!-- ... --> </transition>
因此只需添加 appear
即可解决问题。
这应该可以解决问题:
{
template: `
<transition name="modal">
<div v-if="show">...</div>
</transition>
`,
data() {return {
show: false,
}},
mounted() {
this.show = true
},
}
我认为这种方法(我相信它确实如此)将动画延迟 1 个 Vue tick,并且大量嵌套此类动画元素会明显减慢速度。
Vue.component('modal', {
template: `
<transition name="modal">
<div class="modal-wrapper" v-if="show">
<div class="modal-dialog">
<slot></slot>
</div>
</div>
</transition>
`,
data() {return {
show: false,
}},
mounted() {
this.show = true
}
})
const app = new Vue({
el: '#app',
data: {
showModal: false,
},
})
/* transition */
.modal-enter-active,
.modal-leave-active {
transition: opacity .5s;
}
.modal-enter,
.modal-leave-to {
opacity: 0;
}
.modal-wrapper {
position: absolute;
left: 0; right: 0;
top: 0; bottom: 0;
display: flex;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, .25);
}
.modal-dialog {
max-width: 90%;
padding: 1em;
background: white;
}
<script src="https://vuejs.org/js/vue.js"></script>
<div id="app">
<p><button @click="showModal = true">Show modal</button></p>
<modal v-if="showModal">
<h3>Hello world</h3>
<p>Amet quam alias amet incidunt voluptatum sapiente Mollitia</p>
<p><button @click="showModal = false">Close</button></p>
</modal>
</div>