本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
今天来学习vue3的内置组件,一些是vue2就有的,还有一些是vue2没有,这些都将找到一些具体的例子来记录学习
Transition 和TransitionGroup
第一个注意点: Transition只支持单个元素或组件作为其插槽内容,如果是组件也有限制条件,组件必须只有一个根元素
Transition组件中的元素被插入或移除时,
- vue自动检测元素是否应用了css过渡或动画,如果是,则一些css过渡class会在合适时机被添加或移除
- 如果有监听器的钩子函数,会在适当的时机被调用
- 如果以上都没有,那么DOM的插入,删除等将在浏览器的下一个动画帧后执行
基于css的过渡效果
css过渡class
进入三个calss: v-enter-from v-enter-active v-enter-to 离开三个class: v-leave-from v-leave-active v-leave-to
v-enter-from: 更多的是定义进入动画的初始状态,在元素插入前添加,插入完成后的下一帧移除 v-enter-active: 动画生效阶段,可以定义动画的持续时间,延迟和曲线等 v-enter-to: 定义动画的结束状态,与enter-from是同步的,from被移除的同时,to被添加
v-leave-from: 定义离开动画的起始状态 v-leave-active: 对应的和enter-active一样,定义离开动画的一系列操作 v-leave-to: 定义离开动画的最后状态
给过渡动画命名
我们可以给Transiton组件添加name属性,添加了name属性后,上面的class也就变了v变成name的值
<Transition name="fade">
...
</Transition>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
进阶的动画有贝塞尔曲线等效果
/*
进入和离开动画可以使用不同
持续时间和速度曲线。
*/
.slide-fade-enter-active {
transition: all 0.3s ease-out;
}
.slide-fade-leave-active {
transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-fade-enter-from,
.slide-fade-leave-to {
transform: translateX(20px);
opacity: 0;
}
// 动画的进阶
.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);
}
}
再进一步的话,就是自定义上面的6个class,这样就可以编辑更自用的动画和效果了
<!-- 假设你已经在页面中引入了 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>
性能考量:
上面的例子很多都是transform和opcity之类的,这种都是相对来说不会影响dom结构的,不会触发重排,只有重绘,而如果改变元素的宽高或者margin之类的,就是css布局变化了,会重绘
Transition的钩子函数
<Transition
@before-enter="onBeforeEnter"
@enter="onEnter"
@after-enter="onAfterEnter"
@enter-cancelled="onEnterCancelled"
@before-leave="onBeforeLeave"
@leave="onLeave"
@after-leave="onAfterLeave"
@leave-cancelled="onLeaveCancelled"
>
<!-- ... -->
</Transition>
// 在元素被插入到 DOM 之前被调用
// 用这个来设置元素的 "enter-from" 状态
function onBeforeEnter(el) {}
// 在元素被插入到 DOM 之后的下一帧被调用
// 用这个来开始进入动画
function onEnter(el, done) {
// 调用回调函数 done 表示过渡结束
// 如果与 CSS 结合使用,则这个回调是可选参数
done()
}
// 当进入过渡完成时调用。
function onAfterEnter(el) {}
function onEnterCancelled(el) {}
// 在 leave 钩子之前调用
// 大多数时候,你应该只会用到 leave 钩子
function onBeforeLeave(el) {}
// 在离开过渡开始时调用
// 用这个来开始离开动画
function onLeave(el, done) {
// 调用回调函数 done 表示过渡结束
// 如果与 CSS 结合使用,则这个回调是可选参数
done()
}
// 在离开过渡完成、
// 且元素已从 DOM 中移除时调用
function onAfterLeave(el) {}
// 仅在 v-show 过渡中可用
function onLeaveCancelled(el) {}
复用过渡效果
基于组件化的思想,我们的过渡效果肯定不止一个地方使用,这时就需要封装复用, 在封装Transition组件时则是包装一个组件,并向内传入插槽内容
<Transition name="my-transition" @enter="onEnter" @leave="onLeave">
<!-- 向内传递插槽内容 -->
<slot></slot>
</Transition>
<!-- 之后便可以引入后进行使用 -->
<MyTransition>
<div v-if="show">Hello</div>
</MyTransition>
这里的触发条件的,如果想节点初次渲染时也应用一个过渡效果,有一个属性:appear
元素间过渡
几个按钮只展示一个,在使用v-if v-else-if v-else 时是很适合的场景
<Transition>
<button v-if="docState === 'saved'">Edit</button>
<button v-else-if="docState === 'edited'">Save</button>
<button v-else-if="docState === 'editing'">Cancel</button>
</Transition>
这样的问题是进入的元素和离开的元素的动画是同时开始的,这个时候就可以设置mode="out-in"避免这样的情况出现
TransitonGroup
很多特性和Transiton类似,有一些不同是:
mode属性在这里不支持,
group里面的元素都必须有独一无二的key
CSS 过渡 class 会被应用在列表内的元素上,而不是容器元素上
Keep-Aive
属性:include 和 excude
<!-- 以英文逗号分隔的字符串 -->
<KeepAlive include="a,b">
<component :is="view" />
</KeepAlive>
<!-- 正则表达式 (需使用 `v-bind`) -->
<KeepAlive :include="/a|b/">
<component :is="view" />
</KeepAlive>
<!-- 数组 (需使用 `v-bind`) -->
<KeepAlive :include="['a', 'b']">
<component :is="view" />
</KeepAlive>
设置最大缓存 :max="10
缓存的生命周期
onActivated在组件挂载时也会调用,并且onDeactivated在组件卸载时也会调用。- 这两个钩子不仅适用于
<KeepAlive>缓存的根组件,也适用于缓存树中的后代组件。
一种结构是如果使用了keep-alive时候,就无法重载,必须手动调用初次进入页面的分页查询等,把这些在activede函数中进行调用
这个主要区别是之前的是配合着只需要vue-router中设置keep-alive: true就可以,然后其他的不设置,新的在整体设置上layout中都有区别
teleport
不讲这么多,直接例子:
<button @click="open = true">Open Modal</button>
<Teleport to="body">
<div v-if="open" class="modal">
<p>Hello from the modal!</p>
<button @click="open = false">Close</button>
</div>
</Teleport>
这里的意思就直接把teleport包裹的内容直接的父元素给改变,比如例子中就是直接到了body是他的父元素,to必须是dom中已经存在的真实DOM
suspense
要理解的话,我们先从英文意思中理解: 担心,焦虑,悬念, 也就是说这件事还没有结束前的状态,首先是状态,然后是等状态结束了之后就结束了担心等,哈哈哈这是我对这里命名的理解
内置组件,用来在组件树中协调对异步依赖的处理,我们可以在组件上层等待下层多个嵌套的异步解析完成前的过程中,渲染一个加载状态
<Suspense>
└─ <Dashboard>
├─ <Profile>
│ └─ <FriendStatus>(组件有异步的 setup())
└─ <Content>
├─ <ActivityFeed> (异步组件)
└─ <Stats>(异步组件)
下面这个例子是我们在项目中使用场景的例子: 后续将在项目中实施