最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

徹底搞懂Transition內置組件

 更新時間:2023年07月10日 09:32:07   作者:熊的貓  
這篇文章主要為大家介紹了Transition內置組件使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

<Transition> 作為一個 Vue 中的內置組件,它可以將 進入動畫 和 離開動畫 應用到通過 默認插槽 傳遞給目標元素或組件上。

也許你有在使用,但是一直不清楚它的原理或具體實現(xiàn),甚至不清楚其內部提供的各個 class 到底怎么配合使用,想看源碼又被其中各種引入搞得七葷八素...

本篇文章就以 Transition 組件為核心,探討其核心原理的實現(xiàn),文中不會對其各個屬性再做額外解釋,畢竟這些看文檔就夠了,希望能夠給你帶來幫助?。?!

Transition 內置組件

觸發(fā)條件

<Transition> 組件的 進入動畫 或 離開動畫 可通過以下的條件之一觸發(fā):

  • 由 v-if 所觸發(fā)的切換
  • 由 v-show 所觸發(fā)的切換
  • 由特殊元素 <component name="x"> 切換的動態(tài)組件
  • 改變特殊的 key 屬性

再分類

其實我們可以將以上情況進行 再分類:

  • 組件 掛載 和 銷毀

    • v-if 的變化
    • <component name="x"> 的變化
    • key 的變化
  • 組件 樣式 屬性 display: none | x 設置

    • v-show 的變化

 【擴展】v-if 和 v-for 一起使用時,在 Vue2 和 Vue3 中的不同

  • 在 Vue2 中,當它們處于同一節(jié)點時,v-for 的優(yōu)先級比 v-if 更高,即 v-if 將分別重復運行于每個 v-for 循環(huán)中,也就是 v-if 可以正常訪問 v-for 中的數(shù)據(jù)
  • 在 Vue3 中,當它們處于同一節(jié)點時,v-if 的優(yōu)先級比 v-for 更高,即此時只要 v-if 的值為 false 則 v-for 的列表就不會被渲染,也就是 v-if 不能訪問到 v-for 中的數(shù)據(jù)

六個過渡時機

總結起來就分為 進入 和 離開 動畫的 初始狀態(tài)、生效狀態(tài)、結束狀態(tài),具體如下:

  • v-enter-from

    • 進入 動畫的 起始狀態(tài)
    • 在元素插入之前添加,在元素插入完成后的 下一幀移除
  • v-enter-active

    • 進入 動畫的 生效狀態(tài),應用于整個進入動畫階段
    • 在元素被插入之前添加,在過渡或動畫完成之后移除
    • 這個 class 可以被用來定義進入動畫的持續(xù)時間、延遲與速度曲線類型
  • v-enter-to

    • 進入 動畫的 結束狀態(tài)
    • 在元素插入完成后的下一幀被添加 (也就是 v-enter-from 被移除的同時),在過渡或動畫完成之后移除
  • v-leave-from

    • 離開 動畫的 起始狀態(tài)
    • 在離開過渡效果被觸發(fā)時立即添加,在一幀后被移除
  • v-leave-active

    • 離開 動畫的 生效狀態(tài),應用于整個離開動畫階段
    • 在離開過渡效果被觸發(fā)時立即添加,在 過渡或動畫完成之后移除
    • 這個 class 可以被用來定義離開動畫的持續(xù)時間、延遲與速度曲線類型
  • v-leave-to

    • 離開 動畫的 結束狀態(tài)
    • 在一個離開動畫被觸發(fā)后的 下一幀 被添加 (即 v-leave-from 被移除的同時),在 過渡或動畫完成之后移除

其中的 v 前綴是允許修改的,可以 <Transition> 組件傳一個 name 的 prop 來聲明一個過渡效果名,如下就是將 v 前綴修改為 **`
modal `** 前綴:

<Transition name="modal"> ... </Transition>

Transition 組件 & CSS transition 屬性

以上這個簡單的效果,核心就是兩個時機:

  • v-enter-active 進入動畫的 生效狀態(tài)
  • v-leave-active 離開動畫的 生效狀態(tài)

再配合簡單的 CSS 過渡屬性就可以達到效果,代碼如下:

<template>
  <div class="home">
    <transition name="golden">
      <!-- 金子列表 -->
      <div class="golden-box" v-show="show">
        <img
          class="golden"
          :key="idx"
          v-for="idx in 3"
          src="../assets/golden.jpg"
        />
      </div>
    </transition>
  </div>
  <!-- 錢袋子 -->
  <img class="purse" @click="show = !show" src="../assets/purse.png" alt="" />
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
const show = ref(true)
</script>
<style lang="less" scoped>
.home {
  min-height: 66px;
}
.golden-box {
  transition: all 1s ease-in;
  .golden {
    width: 100px;
    position: fixed;
    transform: translate3d(0, 0, 0);
    transition: all .4s;
    &:nth-of-type(1) {
      left: 45%;
      top: 100px;
    }
    &:nth-of-type(2) {
      left: 54%;
      top: 50px;
    }
    &:nth-of-type(3) {
      right: 30%;
      top: 100px;
    }
  }
  &.golden-enter-active {
    .golden {
      transform: translate3d(0, 0, 0);
      transition-timing-function: cubic-bezier(0, 0.57, 0.44, 1.97);
    }
    .golden:nth-of-type(1) {
      transition-delay: 0.1s;
    }
    .golden:nth-of-type(2) {
      transition-delay: 0.2s;
    }
    .golden:nth-of-type(3) {
      transition-delay: 0.3s;
    }
  }
  &.golden-leave-active {
    .golden:nth-of-type(1) {
      transform: translate3d(150px, 140px, 0);
      transition-delay: 0.3s;
    }
    .golden:nth-of-type(2) {
      transform: translate3d(0, 140px, 0);
      transition-delay: 0.2s;
    }
    .golden:nth-of-type(3) {
      transform: translate3d(-100px, 140px, 0);
      transition-delay: 0.1s;
    }
  }
}
.purse {
  position: fixed;
  width: 200px;
  margin-top: 100px;
  cursor: pointer;
}
</style>

當然動畫的效果是多種多樣的,不僅只是局限于這一種,例如可以配合:

  • CSS 的 transition 過渡屬性(上述例子使用的方案)
  • CSS 的 animation 動畫屬性

gsap 庫

核心原理

通過上述內容其實不難發(fā)現(xiàn)其核心原理就是:

  • 當 組件(DOM) 被 掛載 時,將過渡動效添加到該 DOM 元素上
  • 當 組件(DOM) 被 卸載 時,不是直接卸載,而是等待附加到 DOM 元素上的 動效執(zhí)行完成,然后在真正執(zhí)行卸載操作,即 延遲卸載時機

在上述的過程中,<Transition> 組件會為 目標組件/元素 通過添加不同的 class 來定義 初始、生效、結束 三個狀態(tài),當進入下一個狀態(tài)時會把上一個狀態(tài)對應的 class 移除。

那么你可能會問了,v-show 的形式也不符合 掛載/卸載 的形式呀,畢竟它只是在修改 DOM 元素的 display: none | x 的樣式!

讓源碼中的注釋來回答:

v-if、<component name="x">、key 控制組件 顯示/隱藏 的方式是 掛載/卸載 組件,而 v-show 控制組件 顯示/隱藏 的方式是 修改/重置 display: none | x 屬性值,從本質上看方式不同,但從結果上看都屬于控制組件的 顯示/隱藏,即功能是一致的,而這里所說的 掛載/卸載 是針對大部分情況來說的,畢竟四種觸發(fā)方式中就有三種符合此情況。

實現(xiàn) Transition 組件

所謂 Transition 組件畢竟是 Vue 的內置組件,換句話說,組件的編寫要符合 Vue 的規(guī)范(即 聲明式寫法),但為了更好的理解核心原理,我們應該從 原生 DOM 的過渡開始(即 命令式寫法)探討。

原生 DOM 如何實現(xiàn)過渡?

所謂的 過渡動效 本質上就是一個 DOM 元素在 兩種狀態(tài)間的轉換,瀏覽器 會根據(jù)我們設置的過渡效果 自行完成 DOM 元素的過渡。

而 狀態(tài)的轉換 指的就是 初始化狀態(tài) 和 結束狀態(tài) 的轉換,并且配合 CSS 中的 transition 屬性就可以實現(xiàn)兩個狀態(tài)間的過渡,即 運動過程。

原生 DOM 元素移動示例

假設要為一個元素在垂直方向上添加進場動效:從 原始位置 向上移動 200px 的位置,然后在 1s 內運動回 原始位置。

進場動效

用 CSS 描述

// 描述物體
  .box {
    width: 100px;
    height: 100px;
    background-color: red;
    box-shadow: 0 0 8px;
    border-radius: 50%;
  }
  // 初始狀態(tài)
  .enter-from {
    transform: translateY(-200px);
  }
  // 運動過程
  .enter-active {
    transition: transform 1s ease-in-out;
  }
  // 結束狀態(tài)
  .enter-to {
    transform: translateY(0);
  }

 用 JavaScript 描述

// 創(chuàng)建元素
const div = document.createElement('div')
div.classList.add('box')
// 添加 初始狀態(tài) 和 運動過程
div.classList.add('enter-from')
div.classList.add('enter-active')
// 將元素添加到頁面上
document.body.appendChild(div)
// 切換元素狀態(tài)
div.classList.remove('enter-from')
div.classList.add('enter-to')

從 命令式編程 的步驟上來看,似乎每一步都沒有問題,但實際的過渡動畫是不會生效的,雖然在代碼中我們有 狀態(tài)的切換,但這個切換的操作對于 瀏覽器 來講是在 同一幀中進行的,所以只會渲染 最終狀態(tài),即 enter-to 類所指向的狀態(tài)。

requestAnimationFrame 實現(xiàn)下一幀的變化

window.requestAnimationFrame(callback) 會在瀏覽器在 下次重繪之前 調用指定的 回調函數(shù) 用于更新動畫。

也就是說,單個的 requestAnimationFrame() 方法是在 當前幀 中執(zhí)行的,也就是如果想要在 下一幀 中執(zhí)行就需要使用兩個 requestAnimationFrame() 方法嵌套的方式來實現(xiàn),如下:

// 嵌套的 requestAnimationFrame 實現(xiàn)在下一幀中,切換元素狀態(tài)
  requestAnimationFrame(() => {
    requestAnimationFrame(() => {
      div.classList.remove("enter-from");
      div.classList.add("enter-to");
    });
  });

 transitionend 事件監(jiān)聽動效結束

以上就完成元素的 進入動效,那么在動效結束之后,別忘了將原本和 進入動效 相關的 類 移除掉,可以通過 transitionend 事件 監(jiān)聽動效是否結束,如下

// 嵌套的 requestAnimationFrame 實現(xiàn)在下一幀中,切換元素狀態(tài)
  requestAnimationFrame(() => {
    requestAnimationFrame(() => {
      div.classList.remove("enter-from");
      div.classList.add("enter-to");
      // 動效結束后,移除和動效相關的類
      div.addEventListener("transitionend", () => {
        div.classList.remove("enter-to");
        div.classList.remove("enter-active");
      });
    });
  });

以上就是 進場動效 的實現(xiàn),如下:

離場動效

有了進場動效的實現(xiàn)過程,在定義 離場動效 時就可以選擇和 進場動效 相對應的形式,即 初始狀態(tài)、過渡過程、結束狀態(tài)。

用 CSS 描述

// 初始狀態(tài)
  .leave-from {
    transform: translateY(0);
  }
  // 過渡狀態(tài)
  .leave-active {
    transition: transform 2s ease-out;
  }
  // 結束狀態(tài)
  .leave-to {
    transform: translateY(-300px);
  }

 用 JavaScript 描述

所謂的 離場 就是指 DOM 元素 的 卸載,但因為要有離場動效要展示,所以不能直接卸載對應的元素,而是要 等待離場動效結束之后在進行卸載。

為了直觀一些,我們可以添加一個離場的按鈕,用于觸發(fā)離場動效。

// 創(chuàng)建離場按鈕
  const btn = document.createElement("button");
  btn.innerText = "離場";
  document.body.appendChild(btn);
  // 綁定事件
  btn.addEventListener("click", () => {
    // 設置離場 初始狀態(tài) 和 運動過程
    div.classList.add("leave-from");
    div.classList.add("leave-active");
    // 嵌套的 requestAnimationFrame 實現(xiàn)在下一幀中,切換元素狀態(tài)
    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        div.classList.remove("leave-from");
        div.classList.add("leave-to");
        // 動效結束后,移除和動效相關的類
        div.addEventListener("transitionend", () => {
          div.classList.remove("leave-to");
          div.classList.remove("leave-active");
          // 離場動效結束,移除目標元素
          div.remove();
        });
      });
    });
  });

離場動效,如下:

實現(xiàn) Transition 組件

以上的實現(xiàn)過程,可以將其進行抽象化為三個階段:

  • beforeEnter
  • enter
  • leave

現(xiàn)在要從 命令式編程 轉向 聲明式編程 了,因為我們要去編寫 Vue 組件 了,即基于 VNode 節(jié)點來實現(xiàn),為了和普通的 VNode 作為區(qū)分,Vue 中會為目標元素的 VNode 節(jié)點上添加 transition 屬性:

  • Transition 組件 本身不會渲染任何額外的內容,它只是通過 默認插槽 讀取過渡元素,并渲染需要過渡的元素
  • Transition 組件 作用,是在過渡元素的 VNode 節(jié)點上添加和 transition 相關的 鉤子函數(shù)
<script lang="ts">
import { defineComponent } from 'vue';
const nextFrame = (callback: () => unknown) => {
  requestAnimationFrame(() => {
    requestAnimationFrame(callback)
  })
}
export default defineComponent({
  name: 'Transition',
  setup(props, { slots }) {
    // 返回 render 函數(shù)
    return () => {
      // 通過默認插槽,獲取目標元素
      const innerVNode = (slots as any).default()
      // 為目標元素添加 transition 相關鉤子
      innerVNode.transition = {
        beforeEnter(el: any) {
          console.log(111)
          // 設置 初始狀態(tài) 和 運動過程
          el.classList.add("enter-from");
          el.classList.add("enter-active");
        },
        enter(el: any) {
          // 在下一幀切換狀態(tài)
          nextFrame(() => {
            // 切換狀態(tài)
            el.classList.remove("enter-from");
            el.classList.add("enter-to");
            // 動效結束后,移除和動效相關的類
            el.addEventListener("transitionend", () => {
              el.classList.remove("enter-to");
              el.classList.remove("enter-active");
            });
          })
        },
        leave(el: any) {
          // 設置離場 初始狀態(tài) 和 運動過程
          el.classList.add("leave-from");
          el.classList.add("leave-active");
          // 在下一幀中,切換元素狀態(tài)
          nextFrame(() => {
            // 切換元素狀態(tài)
            el.classList.remove("leave-from");
            el.classList.add("leave-to");
            // 動效結束后,移除和動效相關的類
            el.addEventListener("transitionend", () => {
              el.classList.remove("leave-to");
              el.classList.remove("leave-active");
              // 離場動效結束,移除目標元素
              el.remove();
            });
          })
        }
      }
      // 返回修改過的 VNode
      return innerVNode
    }
  }
})
</script>

最后

從整體來看,Transition 組件 的核心并不算復雜,特別是以 命令式編程 實現(xiàn)之后,但話說回來在 Vue 源碼中實現(xiàn)的還是很全面的,比如:

  • 提供 props 實現(xiàn)用戶自定義類名
  • 提供 內置模式,即先進后出(in-out)、后進先出(enter-to
  • 支持 v-show 方式觸發(fā)過渡效果

以上就是徹底搞懂Transition內置組件的詳細內容,更多關于Transition內置組件的資料請關注腳本之家其它相關文章!

相關文章

  • el-table?表格分頁序號問題小結

    el-table?表格分頁序號問題小結

    這篇文章主要介紹了el-table?表格分頁序號問題小結,本文通過實例代碼圖文效果展示給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2024-04-04
  • vue-router配合ElementUI實現(xiàn)導航的實例

    vue-router配合ElementUI實現(xiàn)導航的實例

    下面小編就為大家分享一篇vue-router配合ElementUI實現(xiàn)導航的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02
  • 使用vue-cli腳手架工具搭建vue-webpack項目

    使用vue-cli腳手架工具搭建vue-webpack項目

    這篇文章主要介紹了使用vue-cli腳手架工具搭建vue-webpack項目,通過幾個默認的步驟幫助你快速的構建Vue.js項目。非常具有實用價值,需要的朋友可以參考下
    2019-01-01
  • Vue3?源碼解讀之?Teleport?組件使用示例

    Vue3?源碼解讀之?Teleport?組件使用示例

    這篇文章主要為大家介紹了Vue3?源碼解讀之?Teleport?組件使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • 淺談vue在html中出現(xiàn){{}}的原因及解決方式

    淺談vue在html中出現(xiàn){{}}的原因及解決方式

    這篇文章主要介紹了淺談vue在html中出現(xiàn){{}}的原因及解決方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • 裝飾者模式在日常開發(fā)中的縮影和vue中的使用詳解

    裝飾者模式在日常開發(fā)中的縮影和vue中的使用詳解

    這篇文章主要為大家介紹了裝飾者模式在日常開發(fā)中的縮影和vue中的使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • VUE 實現(xiàn)element upload上傳圖片到阿里云

    VUE 實現(xiàn)element upload上傳圖片到阿里云

    這篇文章主要介紹了VUE 實現(xiàn)element upload上傳圖片到阿里云,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • VUE前端刪除和批量刪除實現(xiàn)代碼

    VUE前端刪除和批量刪除實現(xiàn)代碼

    這篇文章主要給大家介紹了關于VUE前端刪除和批量刪除的相關資料, 在實際的開發(fā)中,我們可以使用Vue.js來快速實現(xiàn)批量刪除功能,文中給出了詳細的代碼示例,需要的朋友可以參考下
    2023-07-07
  • Vue3中注冊全局的組件,并在TS中添加全局組件提示方式

    Vue3中注冊全局的組件,并在TS中添加全局組件提示方式

    這篇文章主要介紹了Vue3中注冊全局的組件,并在TS中添加全局組件提示方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • vue項目實現(xiàn)登陸注冊效果

    vue項目實現(xiàn)登陸注冊效果

    這篇文章主要為大家詳細介紹了vue項目實現(xiàn)登陸注冊效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09

最新評論

天门市| 防城港市| 佛山市| 石景山区| 安国市| 宁晋县| 深州市| 慈溪市| 黄浦区| 滕州市| 虎林市| 吉林市| 且末县| 吉隆县| 达州市| 潍坊市| 房山区| 犍为县| 石狮市| 永丰县| 延吉市| 葵青区| 防城港市| 崇义县| 九龙城区| 东方市| 营口市| 广汉市| 开鲁县| 三台县| 观塘区| 龙南县| 苍溪县| 昌黎县| 汶上县| 裕民县| 吉水县| 防城港市| 阿拉尔市| 三门峡市| 轮台县|