Teleport组件的应用与vue动画
一、Teleport组件:
1.组件提出原因和应用场景:
有时我们可能会遇到这样的场景:一个组件模板的一部分在逻辑上从属于该组件,但从整个应用视图的角度来看,它在 DOM 中应该被渲染在整个 Vue 应用外部的其他地方。如下图:
页面上从视觉角度看警告板块在整个Vue页面外面
上述内容我们用实现代码是
<!-- 父元素 -->
<template>
<div class="root">
<h3>随便点的内容</h3>
<div>
<Child name="wanzi"/>
</div>
</div>
</template>
<script>
import Child from "./Child.vue";
export default {
components: {
Child
},
};
</script>
<!-- 子元素 -->
<template>
<button @click="open=true">打开</button>
<div v-if="open" class="dialog">
<p>这是一个警告内容</p>{{ name }}
<button @click="open = false">关闭</button>
</div>
</template>
<script>
export default{
data(){
return {
open: false, // 不打开
isDisabled: true, // true表示禁用
}
}
}
</script>
<style scoped>
.dialog{
position: fixed;
z-index: 999;
top: 20%;
left: 50%;
width: 300px;
padding: 20px;
margin-left: -150px;
background-color: rgb(241, 238, 238);
border-radius: 8px;
}
</style>
在子组件的样式中我们发现有position: fixed,但是能够相对于浏览器窗口放置有一个条件,那就是不能有任何祖先元素设置了 transform
、perspective
或者 filter
样式属性。也就是说如果我们想要用 CSS transform
为祖先节点 <div class="root">
设置动画,就会不小心破坏模态框的布局!(父级的动画属性会影响子代的样式,如旋转…这样子代组件就会跟着旋转)
所以Vue提供一个组件:Teleport,下述代码是运用Teleport组件的代码:
<!-- 父元素不变,子元素改变如下 -->
<template>
<button @click="open=true">打开</button>
<Teleport to="html">
<div v-if="open" class="dialog">
<p>这是一个警告内容</p>
<button @click="open = false">关闭</button>
</div>
</Teleport>
</template>
<Teleport>
接收一个 to
prop 来指定传送的目标。to
的值可以是一个 CSS 选择器字符串,也可以是一个 DOM 元素对象。这段代码的作用就是告诉 Vue“把以下模板片段传到html 标签下”。
图片1:
2.使用属性:
<Teleport>
只改变了渲染的 DOM 结构,它不会影响组件间的逻辑关系。也就是说,如果 <Teleport>
包含了一个组件,那么该组件始终和这个使用了 <teleport>
的组件保持逻辑上的父子关系。传入的 props 和触发的事件也会照常工作。
3.禁用Teleport
在某些场景下可能需要视情况禁用 <Teleport>
。举例来说,我们想要在桌面端将一个组件当做浮层来渲染,但在移动端则当作行内组件。我们可以通过对 <Teleport>
动态地传入一个 disabled
prop 来处理这两种不同情况
<Teleport :disabled="true">
...
</Teleport>
4.多个Teleport 共享目标
<Teleport to="html">
<div>A</div>
</Teleport>
<Teleport to="html">
<div>B</div>
</Teleport>
渲染的结果为:
<div id="modals">
<div>A</div>
<div>B</div>
</div>
5.总结:
Teleport可以避免祖先元素transform
、perspective
或者 filter
样式属性带来的影响,从而不用考虑过多的DOM,并且<Teleport>
只改变了渲染的 DOM 结构,它不会影响组件间的逻辑关系。传入的 props 和触发的事件也会照常工作。Teleport属性在不需要时可以被禁用,多个Teleport传到同一个标签层下面是按照传入顺序进行排版
二、Transition动画组件
1.提出原因:
display对过渡样式属性不敏感(v-if/v-show对组件的过渡样式没有显示)
2.介绍:
<Transition>
是一个内置组件,这意味着它在任意别的组件中都可以被使用,无需注册。它可以将进入和离开动画应用到通过默认插槽传递给它的元素或组件上。进入或离开可以由以下的条件之一触发:
- 由
v-if
所触发的切换 - 由
v-show
所触发的切换 - 由特殊元素
<component>
切换的动态组件 - 改变特殊的
key
属性
<template>
<Transition>
<h3 v-if="isShow">这是1个h3</h3>
</Transition>
<button @click="isShow = !isShow">点击</button>
</template>
<script>
export default {
data() {
return {
isShow: true,
};
},
};
</script>
<style scoped>
/*时间点:开始进场(前)*/ /*时间点: 已离场*/
.v-enter-from,
.v-leave-to {
opacity: 0; /* 透明 */
transform: translateX(100px)
}
/*进场动画的时间段: 开始进场前~~~进场完成后*/
/*离场动画的时间段: 开始离场前~~~离场完成后*/
.v-enter-active,
.v-leave-active {
transition: all 3s linear;
}
</style>
上述代码中.v-enter-from, .v-leave-to,.v-enter-active, .v-leave-active都是什么呢我们通过一个图片了解:
-
v-enter-from
:进入动画的起始状态。在元素插入之前添加,在元素插入完成后的下一帧移除。 -
v-enter-active
:进入动画的生效状态。应用于整个进入动画阶段。在元素被插入之前添加,在过渡或动画完成之后移除。这个 class 可以被用来定义进入动画的持续时间、延迟与速度曲线类型。 -
v-enter-to
:进入动画的结束状态。在元素插入完成后的下一帧被添加 (也就是v-enter-from
被移除的同时),在过渡或动画完成之后移除。 -
v-leave-from
:离开动画的起始状态。在离开过渡效果被触发时立即添加,在一帧后被移除。 -
v-leave-active
:离开动画的生效状态。应用于整个离开动画阶段。在离开过渡效果被触发时立即添加,在过渡或动画完成之后移除。这个 class 可以被用来定义离开动画的持续时间、延迟与速度曲线类型。 -
v-leave-to
:离开动画的结束状态。在一个离开动画被触发后的下一帧被添加 (也就是v-leave-from
被移除的同时),在过渡或动画完成之后移除。
3.CSS 的 transition
<Transition>
一般都会搭配原生 CSS 过渡一起使用,正如你在上面的例子中所看到的那样。这个 transition
CSS 属性是一个简写形式,使我们可以一次定义一个过渡的各个方面,包括需要执行动画的属性、持续时间和速度曲线。
4.CSS 的 animation
(如果将transition修改名字则css中v-…就是newName-…)
<template>
<button @click="show = !show">Toggle</button>
<Transition name="bounce">
<p v-if="show" style="margin-top: 20px; text-align: center;">
Hello here is some bouncy text!
</p>
</Transition>
</template>
<script>
export default {
data() {
return {
show: true
}
}
}
</script>
<style>
.bounce-enter-active {
animation: bounce-in 0.5s;
}
.bounce-leave-active {
animation: bounce-in 0.5s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.25);
}
100% {
transform: scale(1);
}
}
</style>
5.CSS 的 Duration
<template>
<!-- -->
<Transition :duration="{enter: 3000, leave: 1000}">
<h3 v-if="isShow">111111111</h3>
</Transition>
<button @click="isShow = !isShow">点击</button>
</template>
<script>
export default {
data() {
return {
isShow: true,
};
},
};
</script>
6.自定义过渡 class
你也可以向 <Transition>
传递以下的 props 来指定自定义的过渡 class:
enter-from-class
enter-active-class
enter-to-class
leave-from-class
leave-active-class
leave-to-class
你传入的这些 class 会覆盖相应阶段的默认 class 名。这个功能在你想要在 Vue 的动画机制下集成其他的第三方 CSS 动画库时非常有用,比如 Animate.css:
<!-- 假设你已经在页面中引入了 Animate.css -->
<Transition
name="custom-classes"
enter-active-class="animate__animated animate__tada"
leave-active-class="animate__animated animate__bounceOutRight"
>
<p v-if="show">hello</p>
</Transition>
en.github.io/animate.css/):
<!-- 假设你已经在页面中引入了 Animate.css -->
<Transition
name="custom-classes"
enter-active-class="animate__animated animate__tada"
leave-active-class="animate__animated animate__bounceOutRight"
>
<p v-if="show">hello</p>
</Transition>