vue3-内置组件

474 阅读5分钟
本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

今天来学习vue3的内置组件,一些是vue2就有的,还有一些是vue2没有,这些都将找到一些具体的例子来记录学习

Transition 和TransitionGroup

第一个注意点: Transition只支持单个元素或组件作为其插槽内容,如果是组件也有限制条件,组件必须只有一个根元素

Transition组件中的元素被插入或移除时,

  1. vue自动检测元素是否应用了css过渡或动画,如果是,则一些css过渡class会在合适时机被添加或移除
  2. 如果有监听器的钩子函数,会在适当的时机被调用
  3. 如果以上都没有,那么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>(异步组件)

下面这个例子是我们在项目中使用场景的例子: 后续将在项目中实施