通过 100 多个技巧学习 Nuxt!

vue-transitions
@morev/vue-transitions

可复用的界面过渡效果,无需 CSS ❤️

Promo image of @morev/vue-transitions package

Stability of "master" branchLicense: MITLast commitRelease versionGitHub Release DateKeywords

@morev/vue-transitions

可复用的界面过渡效果,适用于 Vue 2Vue 3,无需 CSS ❤️

✔️ 通过 props 高度可定制;
✔️ 在 group 模式下,能正确地处理网格/弹性布局;
✔️ 考虑动画元素的初始样式,例如 transformopacity
✔️ 使用通用的 Nuxt 2Nuxt 3 模块更加易用。

演示 / Playground

目录

安装

❗ 要求

  • Node 版本: >= 18.0.0
  • Nuxt 版本 (如果使用): >= 2.17.0 || >= 3.5.0

如果您使用的 Node 或 Nuxt 版本低于指定的版本,该插件将无法工作。


使用 yarn

yarn add @morev/vue-transitions

使用 npm

npm install @morev/vue-transitions

使用 pnpm

pnpm add @morev/vue-transitions

使用 bun

bun add @morev/vue-transitions

对于 Bun 用户的重要提示

该软件包依赖 postinstall 钩子来确定 Vue 版本并提供适当的组件。
默认情况下,Bun 不会执行生命周期钩子,因此要使其工作,您需要在安装后手动将软件包添加到 trustedDependencies 中,然后再次运行 bun install

{
  "trustedDependencies": ["@morev/vue-transitions"]
}

用法

如果您打算在 Nuxt 中使用该库,则可以跳过以下段落。
转到“在 Nuxt 中使用”部分.

软件包导出两个版本的组件

  • 用于 Vue2 的版本,可通过命名导出 /vue2 获得
  • 用于 Vue3 的版本,可通过命名导出 /vue3 获得

但是,还有一个默认导出,它映射到正在使用的本地 Vue 版本。
底层使用了 postinstall npm 钩子。
安装软件包后,脚本将开始检查已安装的 Vue 版本,并根据本地 Vue 版本重定向导出。

它感觉非常健壮,但是如果您担心,请根据您正在使用的版本选择显式命名导入。

顺便说一句,您可以在安装后更改默认导出:只需运行命令 vue-transitions-version-switch <version>

  • 使用 yarn 的示例:yarn vue-transitions-version-switch 2
  • 使用 npx 的示例:npx vue-transitions-version-switch 3

全局注册

使用 Vue3

import { createApp } from 'vue';
import { plugin as vueTransitionsPlugin } from '@morev/vue-transitions';
import '@morev/vue-transitions/styles';

const app = createApp(App);

app.use(vueTransitionsPlugin({
  // Plugin options (optional, described below)
}));

使用 Vue2

import Vue from 'vue';
import { plugin as vueTransitionsPlugin } from '@morev/vue-transitions';
import '@morev/vue-transitions/styles';

Vue.use(vueTransitionsPlugin, {
  // Plugin options (optional, described below)
});
😥 我收到一个错误 “未找到此依赖项”

对于无法解析 exports 字段的环境(例如 Nuxt 2),只需将样式导入替换为文件的直接路径

- import '@morev/vue-transitions/styles';
+ import '@morev/vue-transitions/dist/index.css';

自定义选项

建议在设置自定义选项时使用命名导出 plugin 而不是默认导出,以获取正确的类型信息。

自定义选项允许更改默认属性值。
要更改默认值,请将 defaultProps 键传递给插件设置,列出所需 props 的键值对。
您也可以更改每个组件的默认 props,为此,只需将 componentDefaultProps 键传递给插件设置。

重要提示:这些 props 不会进行验证,因此请确保您使用正确的值定义它们。

import { createApp } from 'vue';
import { plugin as vueTransitionsPlugin } from '@morev/vue-transitions';
import '@morev/vue-transitions/styles';

const app = createApp(App);

app.use(vueTransitionsPlugin({
  // Default duration for all transitions now is `200`
  defaultProps: {
    duration: 200,
  },
  // But for `<transition-expand>` default duration is `500`
  componentDefaultProps: {
    TransitionExpand: {
      duration: 500,
    }
  }
}));

直接导入组件

<template>
  <transition-fade>
    <div v-if="isVisible" class="box">
      Fade transition
    </div>
  </transition-fade>
</template>

<script>
  import { TransitionFade } from '@morev/vue-transitions';

  export default {
    components: { TransitionFade },
  };
</script>

在 Nuxt 中使用

该库通过命名导出 /nuxt 为 Nuxt 2 和 3 导出一个即用型的通用模块。
使用 Nuxt 时,建议使用模块而不是手动安装,因为

  1. Nuxt 允许按需自动导入组件,而不是全局注册,这是一个性能更高的选择。
  2. 这样做速度更快 :)

要使用,请将 @morev/vue-transitions/nuxt 添加到您的 nuxt.config.ts / nuxt.config.jsmodules 部分

export default defineNuxtConfig({
  modules: [
    '@morev/vue-transitions/nuxt',
  ],
  vueTransitions: {
    // The same options as in the plugin itself.
    // You will get an autocomplete using Nuxt 3.
  }
});

享受您的过渡组件!🎉

智能感知

使用 Nuxt 模块可以跳过此部分 - 它会为您完成。

本节仅适用于 VSCode 设置和组件的全局注册。

使用 Vue 2

将 Vue 2 与安装的 Vetur 扩展程序一起使用时,所有组件都应提供提示,无需任何操作

Example of IntelliSense with VSCode and Vetur

使用 Vue 3

将 Vue 3 与安装的 Volar 扩展程序一起使用时,所有组件都应提供提示,无需任何操作

Example of IntelliSense with VSCode and Volar

过渡效果列表

TransitionFade

基本过渡效果,用于更改元素的 opacity。非常简单。

显示代码
<template>
  <transition-fade>
    <div v-if="isVisible">...</div>
  </transition-fade>
</template>

<script>
  import { TransitionFade } from '@morev/vue-transitions';

  export default {
    components: { TransitionFade },
  };
</script>

TransitionExpand

用于操作元素实际大小的过渡效果。
如果您足够老,您可能知道此过渡效果为 jQuery slideUp/slideDown
它也可以像 slideLeftslideRight 一样与 X 轴一起使用(尽管我很难想到真正需要它的场景)。

具有独特的 prop: axis


TransitionSlide

通过 transform: translate() 来操作元素位置的过渡效果。
它需要 offset prop 来计算所需的元素位置,并且可以处理百分比值。

如何使用 offset prop 的示例
<template>
  <!--
    Element will fade in and fade out to top.
    Initial transform is `transform: translate(0, -16px)`
  -->
  <transition-slide :offset="[0, -16]"></transition-slide>

  <!--
    Element will fade in and fade out to bottom left side.
    Initial transform is `transform: translate(-16px, 16px)`
  -->
  <transition-slide :offset="[-16, 16]"></transition-slide>

  <!--
    Element will fade in and fade out to right,
    and the offset will be relative to the element width itself.
    Initial transform is `transform: translate(100%, 0)`
  -->
  <transition-slide :offset="['100%', 0]"></transition-slide>

  <!--
    Element will fade in from top and fade out to bottom,
    and the offset will be relative to the element height itself.

    Transform before element appears: `transform: translate(0, -100%)`
    Transform when element disappears: `transform: translate(0, 100%)`
  -->
  <transition-slide
    :offset="{
      enter: [0, '-100%'],
      leave: [0, '100%']
    }"
  ></transition-slide>
</template>

它会考虑通过 CSS 应用于元素自身的 transform,并将其与定义的 offset 合并。
例如,当您尝试制作居中下拉菜单时,这非常有用。

👀 显示 `transform` 合并的示例
<template>
  <div class="block">
    <!--
      In this case, given the CSS styles,
      initial transform will be calculated to `translate(-50%, -16px)`
    -->
    <transition-slide :offset="[0, -16]">
      <div class="block__dropdown" v-if="isVisible">
        ...
      </div>
    </transition-slide>
  </div>
</template>

<style>
  .block {
    position: relative;
  }

  .block__dropdown {
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
  }
</style>

具有 独特的 prop: offset


TransitionScale

用于操作元素 transform: scale() 的过渡效果。
默认情况下,它将元素从 scale(1) 缩放到 scale(0),但是可以通过 :scale prop 自定义此行为。
它可以通过 axis prop 与不同的轴一起使用。

具有 独特的 props: scale, axis, origin

显示代码示例
<template>
  <!--
    This element appears in `x` axis and disappears in `y`
  -->
  <transition-scale :axis="{ enter: 'x', leave: 'y' }"></transition-scale>

  <!--
    This element behaves like the `transition-expand`,
    but touches only `transform` property
  -->
  <transition-scale transform-origin="50% 0%"></transition-scale>

  <!--
    This element scales just a little when fading in/out.
  -->
  <transition-scale :scale=".8"></transition-scale>

</template>

Props

通用 props

这些属性与每个过渡效果相关

group

组件是否应为 transition-group 组件。

export type TransitionGroup = boolean; // Default: false

示例

<template>
  <div>
    <!--
      To animate a list of items, use `group` prop.
      ⚠️ Don't forget you should pass the `:key` to each item in this case.
    -->
    <transition-fade group>
      <div v-for="item in items" :key="item.id">...</div>
    </transition-fade>
  </div>
</template>
tag

过渡标签,在使用 transition-group 组件的情况下。

export type TransitionTag = string; // Default: 'span'

示例

<template>
  <div>
    <!--
      Passing the tag renders transition component with it.
      It's suitable, for example, for rendering semantic lists:
    -->
    <transition-fade group tag="ul">
      <li v-for="item in items" :key="item.id">...</li>
    </transition-fade>

    <!-- ✨ Rendered HTML: -->
    <ul>
      <li>...</li>
      <li>...</li>
    </ul>
  </div>
</template>
appear

是否在节点的初始渲染时应用过渡效果。其作用与原始的 Vue transition appear prop 完全相同

export type TransitionAppear = boolean; // Default: undefined

示例

<template>
  <div>
    <!--
      This element appears when mounted if `isVisible` is `true` by default.
    -->
    <transition-fade appear>
      <div v-if="isVisible">...</div>
    </transition-fade>
  </div>
</template>
mode

过渡模式.

export type TransitionMode = 'in-out' | 'out-in' | undefined; // Default: undefined

示例

<template>
  <div>
    <!--
      Current element transitions out first, then when complete,
      the new element transitions in.
    -->
    <transition-slide mode="out-in">
      <component :is="currentComponent">...</component>
    </transition-slide>
  </div>
</template>
duration

过渡动画持续时间,单位为毫秒。
如果给出一个对象,则 enterleave 值将分别用于进入和离开过渡。

// Default: 300
export type TransitionDuration = number | { enter: number, leave: number }

示例

<template>
  <div>
    <!--
      If single value provided, the passed amount of milliseconds
      applied to enter and leave animations both.
      This element will appear and disappear within 500ms:
    -->
    <transition-fade :duration="500">
      <div v-if="isVisible">...</div>
    </transition-fade>

    <!--
      If an object given, it SHOULD have `enter` and `leave` keys.
      This element appears in 200ms and disappears within 500ms:
    -->
    <transition-fade :duration="{ enter: 200, leave: 500 }">
      <div v-if="isVisible">...</div>
    </transition-fade>
  </div>
</template>
move-duration

在使用 transition-group 的情况下,更改元素位置的动画持续时间。

尽管 Vue 没有通过 props 设置移动动画持续时间的原生方式,但可以使用 CSS 自定义属性 完成此任务。

👀 显示说明
<!-- This way it can be set dynamically -->
<div style="--move-duration: 300ms;">
  <div class="scale-move"></div>
  <div class="scale-move"></div>
</div>
```

```css
.scale-move {
  transition-duration: var(--move-duration, 300ms);
}
```

</details>

```ts
// Default: 300
export type TransitionMoveDuration = number;
delay

过渡动画延迟时间,单位为毫秒。
如果给出一个对象,则 enterleave 值将分别用于进入和离开过渡。

// Default: 300
export type TransitionDelay = number | { enter: number, leave: number };

示例

<template>
  <div>
    <!--
      If single value provided, then enter and leave animations will wait
      for given amount of milliseconds before run.
      This element will appear and disappear 100ms after
      `isVisible` property changes:
    -->
    <transition-fade :delay="100">
      <div v-if="isVisible">...</div>
    </transition-fade>

    <!--
      If an object given, it SHOULD have `enter` and `leave` keys.
      This element appears immediately and disappears 200ms after
      `isVisible` property changes:
    -->
    <transition-fade :duration="{ enter: 0, leave: 300 }">
      <div v-if="isVisible">...</div>
    </transition-fade>
  </div>
</template>
easing

过渡动画缓动。应为有效的 CSS 过渡时间函数。
如果给出一个对象,则 enterleave 值将分别用于进入和离开过渡。

export type TransitionEasing = string; // Default: 'cubic-bezier(.25, .8, .5, 1)'

示例

<template>
  <div>
    <!--
      If single value provided, then enter and leave animations will use it:
    -->
    <transition-fade easing="ease-out">
      <div v-if="isVisible">...</div>
    </transition-fade>

    <!--
      If an object given, it SHOULD have `enter` and `leave` keys.
      This element uses custom animation known as `bounce-in` for entering
      and simple `ease-out` curve for leaving:
    -->
    <transition-fade
      :easing="{
        enter: 'cubic-bezier(0.6, 0, 0.4, 2)',
        leave: 'ease-out'
      }"
    >
      <div v-if="isVisible">...</div>
    </transition-fade>
  </div>
</template>
no-opacity

是否动画元素的 opacity

默认情况下,每个过渡效果除了主属性外,还会操作 opacity
但是,有时不需要这样做 - 例如,在实现从屏幕边缘出现的模态面板时。

该 prop 显然不适用于 transition-fade 组件。

export type TransitionNoOpacity = boolean; // Default: false

示例

<template>
  <div>
    <!--
      This panel appears from the right edge of the screen,
      while its transparency remains unchanged.
    -->
    <transition-slide :offset="['100%', 0]" no-opacity>
      <div class="panel" v-if="isVisible">...</div>
    </transition-slide>
  </div>
</template>

<style>
  .panel {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    background: #ffffff;
    width: 400px;
  }
</style>
no-move

是否动画元素位置的更改,在使用 transition-group 的情况下。

默认情况下,当使用 group 模式时,当删除元素时,其余元素会平滑地更改其位置。
它们被赋予绝对定位并脱离流动,因此父容器的高度会塌陷。

通常这不是问题,但有时 - 例如,当使用 transition-expand 和彼此下方顺序放置的元素时,它看起来很粗糙。
使用此选项,您可以在这种情况下实现更令人愉悦的元素行为。

export type TransitionNoMove = boolean; // Default: false

示例

<template>
  <div>
    <!--
      In this case, the height of the parent element (`ul`) changes smoothly.
    -->
    <transition-expand group no-move tag="ul">
      <li v-for="item in items" :key="item.id">...</li>
    </transition-expand>
  </div>
</template>

TransitionExpand 的独有 props

axis

元素应按其扩展的轴。
如果给出一个对象,则 enterleave 值将分别用于进入和离开过渡。

type ExpandAxisValue = 'x' | 'y'; // Default: 'y'
export type TransitionExpandAxis = ExpandAxisValue | { enter: ExpandAxisValue, leave: ExpandAxisValue }

TransitionSlide 的独有 props

offset

元素在过渡之前/之后的 xy 轴偏移量。
应为整数或百分比值的字符串表示形式(例如 '100%')。

数字值被视为 px 偏移量,以 % 符号结尾的字符串值被视为 元素宽度/高度的百分比
示例和说明

如果给出一个对象,则 enterleave 值将分别用于进入和离开过渡。

type SlideOffsetValue = [number | string, number | string];

// Default: [0, -16]
export type TransitionSlideOffset = SlideOffsetValue | { enter: SlideOffsetValue, leave: SlideOffsetValue }

TransitionScale 的独有 props

axis

要动画的缩放轴。

* `both` (uses `transform: scale()`)
* `x` (uses `transform: scaleX()`)
* `y` (uses `transform: scaleY()`)

示例和说明

如果给出一个对象,则 enterleave 值将分别用于进入和离开过渡。

type ScaleAxisValue = 'x' | 'y' | 'both';

// Default: 'both'
export type TransitionScaleAxis = ScaleAxisValue | { enter: ScaleAxisValue, leave: ScaleAxisValue }
origin

应用于元素的 transform-origin CSS 属性。\

如果给出一个对象,则 enterleave 值将分别用于进入和离开过渡。

示例和说明

如果给出一个对象,则 enterleave 值将分别用于进入和离开过渡。

// Default: '50% 50%'
export type TransitionScaleAxis = string | { enter: string, leave: string }
scale

过渡之前/之后的元素缩放值。应为介于 01 之间的数字。

如果给出一个对象,则 enterleave 值将分别用于进入和离开过渡。

示例和说明

如果给出一个对象,则 enterleave 值将分别用于进入和离开过渡。

// Default: 0
export type TransitionScaleScale = number | { enter: number, leave: number }

事件

组件不提供任何特殊事件,但会触发所有标准过渡事件

  • before-enter
  • enter
  • after-enter
  • enter-cancelled
  • before-leave
  • leave
  • after-leave
  • enter-leave