透過 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 模式下正確地與 grid/flex 佈局協同運作;
✔️ 考量動畫元素的初始樣式,例如 transformopacity
✔️ 透過通用 Nuxt 2Nuxt 3 模組更易於使用。

DEMO / 範例

目錄

安裝

❗ 需求條件

  • 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 hook 來判斷 Vue 版本並提供正確的元件。
預設情況下,Bun 不會執行生命週期 hooks,因此為了使其運作,您需要在安裝後手動將此套件新增至 trustedDependencies,然後再次執行 bun install

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

用法

如果您打算將此函式庫與 Nuxt 搭配使用,則可以跳過以下段落。
前往「與 Nuxt 搭配使用」章節.

套件匯出兩個版本的元件

  • 用於 Vue2 的版本可透過具名匯出 /vue2 取得
  • 用於 Vue3 的版本可透過具名匯出 /vue3 取得

但是,也有一個預設匯出對應到正在使用的 Vue 本機版本。
在底層,它使用了 postinstall npm hook。
安裝套件後,腳本將開始檢查已安裝的 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.
  }
});

盡情享受您的轉場元件! 🎉

IntelliSense

您可以使用 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
它也可以與 X 軸搭配運作,例如 slideLeftslideRight(雖然我難以想出真正需要它的情境)。

具有 獨特的 propaxis


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>

具有 獨特的 propoffset


TransitionScale

透過 transform: scale() 操控元素 transform: scale() 的轉場效果。
預設情況下,它會將元素從 scale(1) 縮放至 scale(0),但此行為可以透過 :scale prop 進行自訂。
它可以透過 axis prop 與不同的軸搭配運作。

具有 獨特的 propsscaleaxisorigin

顯示程式碼範例
<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 轉場效果 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

轉場效果動畫 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