Vue現(xiàn)代化使用方法(三)

混合

組件系統(tǒng)是Vue的核心,如何合理的規(guī)劃組件,是我們在開發(fā)中需要深入思考的問題,我個人習慣把一些組件使用邏輯和方法,從組件中拆分出來,放到獨立文件,最后通過混合的方式,引入相關邏輯,這樣可以在一定層面上把組件再進行一次解耦,做到只要切換不同的混合文件就能提供新功能的能力

// 在hello-world項目目錄下,建立basic.vue,在其中輸入下面內(nèi)容
<template>
</template>
<script>
    export default {
        data () {
            return {
                basicInfo: 'basicInfo'
            }
        },
        created () {
            console.log('from basic');
        }
    }
</script>
...
// 在index.vue中引入這個文件,并且進行混合
import basic from './basic.vue'; 
...
export default {
        mixins: [basic],
...
// 在index.vue的模板中添加下面內(nèi)容
<p>{{basicInfo}}</p>        

此時在頁面可以正常渲染出basicInfo的插值,還會打印出basic中的log信息,下面做如下改造:

// 在basic.vue下,添加sayInfo方法
methods: {
    sayInfo () {
        console.log(`from basic.vue,info:${this.basicInfo}`);
    }
}
...
// 在index.vue的模板下,做下面調(diào)整
<p @click="sayInfo">{{basicInfo}}</p>

這時如果你點擊頁面就會發(fā)現(xiàn)控制臺輸出定義在basic.vue中的信息,可以假設如果我們切換成另外一個也有sayInfo的組件,這時點擊頁面就會響應另外一個組件中的同名事件,這樣就達到了切換不同混合邏輯,組件功能也就不同

// 直接調(diào)用被混入對象的值,在basic.vue中是沒有info的值,但是因為在index.vue中有info值,這時點擊元素一樣可以正常輸出info的值
sayInfo () {
    console.log(`from basic.vue,info:${this.basicInfo}`);
    console.log(this.info);
}

進行混合時有下面幾個規(guī)則需要注意:

  • 當組件和引入的混合組件有數(shù)據(jù)沖突時,會以組件的數(shù)據(jù)為準
// 在basic.vue的文件中,添加info數(shù)據(jù)
data () {
    return {
        basicInfo: 'basicInfo',
        info: 'from basic'
    }
},

此時按普通組件的邏輯分析,sayInfo應該輸出basic.vue的info值,但是因為組件數(shù)據(jù)的優(yōu)先級高于混合組件,當出現(xiàn)數(shù)據(jù)沖突時,保留組件的數(shù)據(jù),所以此時info的值依然還是index.vue中定義的info值,data,methods,computed,directives(值為對象的選項)中的同名值都會產(chǎn)生覆蓋

  • 部分鉤子函數(shù)數(shù)據(jù)會產(chǎn)生合并為不是覆蓋
// index.vue的模板做如下改造
<p @click="sayInfo">{{basicInfo}}</p>
<button @click="changeInfo">改變info值</button>
...
// index.vue添加方法
methods: {
    changeInfo () {
        this.info = 'change Info';
    }
}
...
// index.vue添加對info數(shù)據(jù)的監(jiān)聽
watch: {
    info () {
        console.log('watch basic.vue info值發(fā)生改變');
    }
},
...
// index.vue的created鉤子函數(shù)添加如下內(nèi)容
created () {
    console.log('from index.vue created');
},
...
// basic.vue的created鉤子函數(shù)添加如下內(nèi)容
created () {
    console.log('from basic');
},
// basic.vue添加對info監(jiān)聽的watch方法
watch: {
    info () {
        console.log('watch basic.vue info值發(fā)生改變');
    }
},

在控制臺會輸出

from basic
from index.vue created
...
watch basic.vue info值發(fā)生改變
watch index.vue info值發(fā)生了變化

同名鉤子函數(shù)將混合為一個數(shù)組,因此都將被調(diào)用。混入對象的鉤子將在組件自身鉤子之前調(diào)用。

上面介紹的都是在組件內(nèi)的進行混合,Vue提供了Vue.mixin用來定義進行全局混合,但這種方式太過暴力,會影響所有的組件實例以及第三方模板,如果有要在全局添加相關功能的需求可以使用插件來添加。

插件

插件通常會為 Vue 添加全局功能。插件的范圍沒有限制——一般有下面幾種:

  • 添加全局方法或者屬性
  • 添加全局資源:指令/過濾器/過渡等
  • 通過全局 mixin 方法添加一些組件選項
  • 添加 Vue 實例方法,通過把它們添加到 Vue.prototype 上實現(xiàn)
  • 一個庫,提供自己的 API,同時提供上面提到的一個或多個功能

Vue的作者在插件編寫方面提供了很好的封裝,我們可以很容易的編寫出一個Vue插件。

// 在項目下新建一個plugin.js,在其中編寫如下內(nèi)容
let plugin = {};
plugin.install = (Vue, options) => {
    Vue.$msg = 'from plugin';
};
module.exports = plugin;
...
// 在項目的index.js中引入這個文件,并通過Vue.use使用這個插件
import plg from './plugin'; // 引入plugin.js插件

Vue.use(plg);
console.log('Vue' + Vue.$msg);

這時在控制臺就能輸出,我們剛剛在插件中定義的信息,通過上面的例子,我們可以看出Vue的插件應當有一個公開方法install。這個方法的第一個參數(shù)是 Vue 構造器,第二個參數(shù)是一個可選的選項對象,在方法內(nèi)部可以定義如下幾種信息:

MyPlugin.install = function (Vue, options) {
  // 1. 添加全局方法或屬性
  Vue.myGlobalMethod = function () {
    // 邏輯...
  }

  // 2. 添加全局資源
  Vue.directive('my-directive', {
    bind (el, binding, vnode, oldVnode) {
      // 邏輯...
    }
    ...
  })

  // 3. 注入組件
  Vue.mixin({
    created: function () {
      // 邏輯...
    }
    ...
  })

  // 4. 添加實例方法
  Vue.prototype.$myMethod = function (methodOptions) {
    // 邏輯...
  }
}

全局方法或全局屬性就如上例一樣,加掛到Vue上,需要通過訪問Vue來訪問綁定到全局的方法和屬性。在組件內(nèi)部要訪問綁定到Vue的全局變量,需要做如下改造:

// 引入Vue,以及插件
import Vue from 'vue';
import plg from './plugin'; // 引入plugin.js插件
Vue.use(plg);
...
// 這時在組件內(nèi)部也可以正常訪問綁定在Vue的全局方法或全局屬性
mounted () {
    console.log('Vue' + Vue.$msg);
}

如果要加到實例上,可以使用Vue.prototype添加

plugin.install = (Vue, options) => {
    Vue.prototype.$msg = 'from plugin';
};
...
// 此時在在實例內(nèi)部可以使用this進行訪問
mounted () {
    console.log('Vue' + this.$msg);
},

在使用組件時可以參入?yún)?shù)

Vue.use(plg, {value:'from index.js'});
...
// 在插件中就可以通過options進行使用
Vue.prototype.$msg = options.value;

過渡

Vue 在插入、更新或者移除 DOM 時,提供多種不同方式的應用過渡效果。

單元素/組件過渡

Vue 提供了 transition 的封裝組件,在下列情形中,可以給任何元素和組件添加 entering/leaving過渡

  • 條件渲染 (使用 v-if)
  • 條件展示 (使用 v-show)
  • 動態(tài)組件
  • 組件根節(jié)點
// 在index.vue的模板頁中添加如下代碼
<button @click="changeShow">過渡效果</button>
<transition>
    <p v-if="showFlag">過渡區(qū)域</p>
</transition>
...
// index.vue的methods下添加下面方法
methods: {
    changeShow () {
        this.showFlag = !this.showFlag;
    }
}

這時點擊按鈕p標簽會在隱藏和顯示中切換,不過這時沒有過渡的效果,如果要加過渡效果可以添加name屬性。

<transition name="fade">
...
// 在index.vue中添加style標簽,在其中添加相關樣式文件
<style>
    .fade-enter-active, .fade-leave-active {
        transition: opacity 1s;
    }
    .fade-enter, .fade-leave-to {
        opacity: 0;
    }
    .fade-enter-to, .fade-leave {
        opacity: 1;
        color: red;
    }
</style>

當插入或刪除包含在 transition 組件中的元素時,Vue 將會做以下處理:

  • 自動嗅探目標元素是否應用了 CSS 過渡或動畫,如果是,在恰當?shù)臅r機添加/刪除 CSS 類名。
    在進入/離開的過渡中,會有 6 個 class 切換。

    • v-enter:定義進入過渡的開始狀態(tài)。在元素被插入時生效,在下一個幀移除。

    • v-enter-active:定義過渡的狀態(tài)。在元素整個過渡過程中作用,在元素被插入時生效,在 transition/animation 完成之后移除。這個類可以被用來定義過渡的過程時間,延遲和曲線函數(shù)。

    • v-enter-to: 2.1.8版及以上 定義進入過渡的結束狀態(tài)。在元素被插入一幀后生效 (與此同時 v-enter 被刪除),在 transition/animation 完成之后移除。

    • v-leave: 定義離開過渡的開始狀態(tài)。在離開過渡被觸發(fā)時生效,在下一個幀移除。

    • v-leave-active:定義過渡的狀態(tài)。在元素整個過渡過程中作用,在離開過渡被觸發(fā)后立即生效,在 transition/animation 完成之后移除。這個類可以被用來定義過渡的過程時間,延遲和曲線函數(shù)。

    • v-leave-to: 2.1.8版及以上 定義離開過渡的結束狀態(tài)。在離開過渡被觸發(fā)一幀后生效 (與此同時 v-leave 被刪除),在 transition/animation 完成之后移除。

class的切換可以簡單理解成,當元素剛插入時,會插入v-enter(v-就是transition中的name屬性)和v-enter-active兩個class,然后在下一幀會刪除v-enter,添加上v-enter-to,最后在transition/animation執(zhí)行完成后,會直接刪除v-enter-to和v-enter-active這兩個class,當元素離開時和進入時一致,剛開始離開就添加v-leave和v-leave-active這兩個class,然后在下一幀就刪除v-leave添加v-leave-to。在顯示和離開的整個過程中v-enter-active和v-leave-active是一直存在的,所以才會說在這兩個類中定義過渡時間,延遲和曲線函數(shù),結合上面的例子,我們來分析下,整個執(zhí)行過程:

  1. 當我們點擊按鈕時,頁面中的p標簽進入離開狀態(tài),所以Vue會在p標簽上創(chuàng)建兩個class,fade-leave、fade-leave-active
  2. 進到下一幀,fade-leave會被刪除,fade-leave-to會被添加,所以在點擊標簽的時候才會有字體會猛的變成紅色,然后又變回黑色,然后按照fade-leave-active設定的動畫,逐漸消失。
  3. 文字消失后,我們再次點擊按鈕,文字會先成紅色,然后逐漸展示出來,最后變成黑色,這也是因為整個class添加的順序是,先添加fade-enter,fade-enter-active然后再添加fade-enter-to,最后在全部刪除,分析相關的樣式代碼,我們能很清晰的看出正規(guī)邏輯的執(zhí)行過程。

按官網(wǎng)的說法,由于動畫的不同,Vue針對transition和animation在添加和移除相關class的時機會有一些區(qū)別,這個區(qū)別主要集中在v-enter類名上,下面做如下改造,來驗證這個說法:

// 在index.vue的style下,添加下面代碼
.bounce-enter {
    color: red;
    font-size: 28px;
}
.bounce-enter-active {
    animation: bounce-in 2s;
}
.bounce-leave {
    color: red;
}
.bounce-leave-active {
    animation: bounce-in 2s reverse;
}
@keyframes bounce-in {
    0% {
        opacity: 0.5;
    }
    100% {
        opacity: 1;
    }
}
...
// 對模板中的代碼也做相關調(diào)整,animationstart和animationend是動畫開始和結束的監(jiān)聽事件
<transition name="bounce">
    <p @animationstart="startEvent" @animationend="endEvent" v-if="showFlag">過渡區(qū)域</p>
</transition>
...
// 添加兩個動畫的監(jiān)聽事件
startEvent (e) {
    console.log('動畫執(zhí)行開始');
    console.log(e.srcElement.className);
    console.log(new Date().getTime());
    console.log(this.showFlag);
},
endEvent (e) {
    console.log('動畫執(zhí)行完畢');
    console.log(e.srcElement.className);
    console.log(new Date().getTime());
    console.log(this.showFlag);
}

通過控制臺的輸出,我們可以很明顯的看出當發(fā)生過渡時,class的變化,當元素移除時,class變化是先為:bounce-leave bounce-leave-active,然后再變?yōu)椋篵ounce-leave-active bounce-leave-to,元素添加時,class的變化是先為:bounce-enter bounce-enter-active,然后再變?yōu)閎ounce-enter-active bounce-enter-to,這個值的變化也驗證了,我們之前所說的執(zhí)行邏輯。如果你仔細觀察頁面中元素的變化也能看出對應的樣式也是生效的,不過這里有問題,當你多點擊幾次,會發(fā)現(xiàn)好像v-enter對應的樣式并不是每一次都生效,有時會感覺Vue在執(zhí)行時會忽略v-enter/v-leave的樣式,這個問題暫時還沒想明白,不知道是不是我設置的樣式的問題?

另外要注意的是必須在v-enter-active、v-leave-active或v-enter-to、v-leave-to中設置transition或animation動畫,要不整個過渡效果看起來像是沒有執(zhí)行一樣,頁面很快的發(fā)生變化,可以做如下的驗證:

// 隱藏transition
.fade-enter-active, .fade-leave-active {
    /*transition: opacity 2s;*/
    color: #00aceb;
    font-size: 30px;
}

此時頁面如預期一樣,發(fā)生了很快的變化,完全看不出有什么過渡效果

// 這時雖然可以這樣改造,讓過渡繼續(xù)生效,不過從整個執(zhí)行過程上來看,顯然沒有放到active上好
.fade-enter-to, .fade-leave-to {
    transition: opacity 2s;
}

除了可以使用transition對應的name自動生成的class,還可以指定某個class:

enter-class                 // 替換v-enter
enter-active-class          // 替換v-enter-active
enter-to-class              // 替換v-enter-to
leave-class                 // 替換v-leave
leave-active-class          // 替換v-leave-active
leave-to-class              // 替換v-leave-to

可以做如下驗證:

<transition name="fade" enter-active-class="intoClass" enter-to-class="externalClass">
...
.externalClass {
    color: #faf2cc;
}
.intoClass {
    transition: opacity 2s;
}

這時你切換頁面會發(fā)現(xiàn)當元素重新插入時,綁定的class就變成了intoClass和externalClass,這種規(guī)則,對引入外部動畫庫有比較友好的支持,只需要把需要執(zhí)行的相關class進行替換。

使用type設定Vue監(jiān)聽動畫的類型

過渡效果如果只是transition或者只是animation,Vue可以很明顯的知道要監(jiān)聽什么,但當過渡和動畫同時存在時,如果不指定監(jiān)聽類型,Vue就不能明確的知道監(jiān)聽哪個。

// 樣式文件做相關修改,過渡和動畫同時存在
.fade-enter-active, .fade-leave-active {
    transition: opacity 5s;
    animation: bounce-in 2s reverse;
}
@keyframes bounce-in {
    0% {
        transform: scale(0);
    }
    50% {
        transform: scale(1.5);
    }
    100% {
        transform: scale(1);
    }
}

這時點擊頁面如果移除元素,會發(fā)現(xiàn)class在transition執(zhí)行完成才會移除,如果此時是以transition為主,是沒有問題的,但如果想以animation為主,就要設定type值

// type值可以為animation,transition
<transition name="fade" type="animation">

這時再點擊頁面會發(fā)現(xiàn)此時過渡效果是以animation的動畫為準,如果你希望動畫要持續(xù)足夠長的時間,可以保證所有動畫過渡都執(zhí)行完,可以使用duration屬性,設定過渡持續(xù)時間。

// duration單位是毫秒,下面這樣設定表示,過渡持續(xù)8秒(進入和離開都是8秒)
<transition name="fade" type="animation" :duration="8000">
...
// 還可以設定的更詳細,{enter: 2000, leave: 8000}進入時過渡時間持續(xù)2秒,離開時持續(xù)8秒
<transition name="fade" type="animation" :duration="{enter: 2000, leave: 8000 }">
  • 如果過渡組件提供了 JavaScript 鉤子函數(shù),這些鉤子函數(shù)將在恰當?shù)臅r機被調(diào)用。

除了普通的css動畫庫還有以js為主的動畫庫,Vue提供這方面的能力,估計很大一方面就是讓Vue能和這些js庫結合,使用js鉤子函數(shù)會使動畫操作更為準確,能比較精確的控制在某些狀態(tài)下頁面行為,這是css動畫不好實現(xiàn)的地方,官方文檔在這部分使用的是Velocity.js這個動畫庫(隱隱的神傷。。想寫原生的動畫,怎么實現(xiàn)都有問題,標記下回頭找找原因)

// 在項目最外層目錄運行下面命令,安裝velocity-animate動畫庫
npm install velocity-animate --save
...
// 在index.vue中引入這個庫
import Velocity from 'velocity-animate'; // 引入velocity-animate動畫庫
...
// index.vue模板文件做如下修改
<transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter" @enter-cancelled="enterCancelled" @before-leave="beforeLeave" @leave="leave" @after-leave="afterLeave" @leave-cancelled="leaveCancelled" :css="false">
...
// index.vue添加相關方法
beforeEnter (el) {
    console.log('beforeEnter');
    el.style.opacity = 0;
    el.style.transformOrigin = 'left';
},
enter (el, done) {
    console.log('enter');
    Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 });
    Velocity(el, { fontSize: '1em' }, { complete: done });
},
afterEnter (el) {
    console.log('afterEnter');
},
enterCancelled (el) {
    console.log('enterCancelled');
},
beforeLeave (el) {
    console.log('beforeLeave');
},
leave (el, done) {
    console.log('leave');
    Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 });
    Velocity(el, { rotateZ: '100deg' }, { loop: 2 });
    Velocity(el, {
        rotateZ: '45deg',
        translateY: '30px',
        translateX: '30px',
        opacity: 0
    }, { complete: done })
},
afterLeave (el) {
    console.log('afterLeave');
},
leaveCancelled (el) {
    console.log('leaveCancelled');
}

點擊按鈕,可以看到控制臺依次輸出

beforeEnter
enter
afterEnter(動畫結束后輸出)
...
beforeLeave
leave
afterLeave(動畫結束后輸出)

在進入或移除動畫沒有運行完成時,點擊按鈕,中斷動畫這時就會輸出

enterCancelled/leaveCancelled

官方文檔上說,在 enter 和 leave 中,回調(diào)函數(shù) done 是必須的 。否則,它們會被同步調(diào)用,過渡會立即完成。注意leave (el, done)和enter (el, done)多接收了一個參數(shù),并在{ complete: done }中進行了觸發(fā),沒特別看出過渡立即完成這個效果,可能是和使用了Velocity動畫庫有關,不過如果不添加這個done的回調(diào),after-enter的鉤子函數(shù)是不能正常調(diào)用,并且在下一次動畫中會先執(zhí)行enter-cancelled的鉤子函數(shù)。

:css="false"是忽略對過渡元素添加class(官方文檔上說時不對過渡元素進行css檢查,沒特別看出來,不過不加這個屬性,過渡元素會添加v-enter,v-enter-active等class,添加了就不會添加)

使用appear設定元素初始化時的過渡/動畫

通過設定appear屬性可以讓組件開始渲染時一樣有過渡效果

// 添加appear屬性是表示啟用此特性,appear-class,appear-to-class,appear-active-class和v-enter,v-enter-to,v-enter-active存在周期一致
<transition appear appear-class="custom-appear-class" appear-to-class="custom-appear-to-class" appear-active-class="custom-appear-active-class">
    <p v-if="showFlag">過渡區(qū)域</p>
</transition>
...
// 樣式文件中添加如下內(nèi)容
.custom-appear-class{
    font-size: 40px;
    color: red;
    opacity: 0;
}
.custom-appear-to-class {
    font-size: 18px;
}
.custom-appear-active-class{
    opacity: 1;
    transition: all 5s;
}
...
// 這時要把showFlag改為true,才能看出這個效果,因為這個加載時的過渡效果只會在進入時啟用,渲染完成后就不會再使用
showFlag: true,

這時刷新頁面就會發(fā)現(xiàn)當前元素在第一次渲染時會有一個進入過渡效果,再進行相關操作,這個過渡效果也不會出來

多元素過渡

在某些情況下會碰到在一個區(qū)域存在因為不同條件展示不同元素的情況,比如

// 此時這個key值的其實并不是很必要,因為button并不會像input元素那樣存在用戶輸入的緩存信息,但Vue官方建議在這種情況下加上key讓元素強制重新渲染,讓過渡動畫可以正常觸發(fā),如果此時不加key值,因為我們改動的只是文案,Vue會盡可能復用代碼,并不會重新渲染當前元素,也就不會出現(xiàn)過渡效果
<button @click="changeState">改變文字</button>
<transition name="fade">
    <button :key="docState">
        {{ buttonMessage }}
    </button>
</transition>
...
// data下添加docState
docState: 'saved',
...
// methods下添加changeState
changeState () {
    switch (this.docState) {
        case 'saved':
            this.docState = 'edited';
            break;
        case 'edited':
            this.docState = 'editing';
            break;
        case 'editing':
            this.docState = 'saved';
            break;
    }
},

此時點擊頁面我們會看到一個比較丑陋的按鈕切換效果,一個按鈕正在消失,另一個按鈕同時出現(xiàn),此時我們可以借助Vue提供的過渡模式來使進出過渡切換的更為自然

// mode: out-in(當前元素先進行過渡,完成之后新元素過渡進入); in-out(新元素先進行過渡,完成之后當前元素過渡離開)
<transition name="fade" mode="out-in">

這時頁面的過渡效果就比較自然了,一個元素消失,另外一個元素漸隱出現(xiàn),如果是多個組件的過渡可以使用動態(tài)組件來實現(xiàn)

// 在index.vue的模板中做如下調(diào)整
<button @click="changeTab">改變tab</button>
<transition name="fade" mode="out-in">
    <component :is="showTabView"></component>
</transition>
...
// 添加相關方法
changeTab () {
    switch (this.showTabView) {
        case 'gameList':
            this.showTabView = 'newsList';
            break;
        case 'newsList':
            this.showTabView = 'sportList';
            break;
        case 'sportList':
            this.showTabView = 'gameList';
            break;
    }
}

這時在頁面端就添加了對動態(tài)組件的過渡效果,上面我們看了單個元素的顯示隱藏觸發(fā)的過渡效果,和在同一區(qū)域不同元素和組件切換時的過渡效果,除此之外,還有列表的過渡效果沒有講,在官方文檔,直接告訴我們對列表使用transition-group,但為什么不可以使用transition呢,我們使用一個實例來驗證下:

// index.vue的模板改造
<button @click="add">Add</button>
<button @click="remove">Remove</button>
<ul class="ulList">
<transition name="fade">
    <li v-for="item in numList">{{item}}</li>
</transition>
</ul>
...
// data添加下面屬性
numList: [1, 2, 3, 4, 5, 6, 7, 8, 9],
nextNum: 10,
...
// 添加下面樣式
.ulList li {
    list-style: none;
}
...
// 添加相關方法
randomIndex: function () {
    return Math.floor(Math.random() * this.numList.length)
},
add: function () {
    this.numList.splice(this.randomIndex(), 0, this.nextNum++)
},
remove: function () {
    this.numList.splice(this.randomIndex(), 1)
}

這時頁面會直接提示transition只能用在單個元素,如果要使用在列表元素需要使用transition-group。

// 換成transition-group,但此時子元素li沒有添加key值,一樣報錯提示transition-group的子元素必須包含key值
<transition-group name="fade">
    <li v-for="item in numList">{{item}}</li>
...
// 添加key值
    <li v-for="item in numList" :key="item">{{item}}</li>

此時頁面渲染為

<button>Add</button> 
<button>Remove</button> 
<ul class="ulList">
    <span>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
        <li>7</li>
        <li>8</li>
        <li>9</li>
    </span>
</ul>
...
// ul下的span是transition-group默認進行添加的,如果你想改動可以使用tag屬性
// 沒看到官方文檔上說如何在包裹外層元素時,同時添加元素的class,這個問題感覺也沒那么重要,在外面包裹一個div直接添加class就行了
<button @click="add">Add</button>
<button @click="remove">Remove</button>
<div class="ulList">
    <transition-group name="list" tag="ul">
        <li v-for="item in numList" :key="item">{{item}}</li>
    </transition-group>
</div>

此時頁面如果再添加元素,就會有過渡效果,不過此時過渡雖然有了,但是有些僵硬,一個元素插入,其他元素直接就跑到該到的位置,沒有流暢感,這里Vue使用了FLIP動畫(后面說動畫時會詳細講解)來解決這個問題

// 在樣式文件中添加如下內(nèi)容
.list-move {
    transition: transform 1s;
}

此時頁面的渲染就會在元素插入時,其他元素一起過渡起來,看起來就變的很流暢,除了自動添加的樣式(因為針對過渡元素設定的是list過渡,這時的list-move是Vue自動判斷的,如果不需要這個自動添加的,可以使用:move-class設定不同的class)

  • 如果沒有找到 JavaScript 鉤子并且也沒有檢測到 CSS 過渡/動畫,DOM 操作 (插入/刪除) 在下一幀中立即執(zhí)行。

與第三方庫的結合達到數(shù)據(jù)元素本身的過渡

上面介紹的都是以元素為基本條件觸發(fā)的過渡,如果只是元素本身數(shù)據(jù)的更新,這時要進行過渡就要引入第三方庫來實現(xiàn)這些過渡,這些包括且不限于:

  • 數(shù)字和運算
  • 顏色的顯示
  • SVG 節(jié)點的位置
  • 元素的大小和其他的屬性

這部分的內(nèi)容我理解和動畫掛鉤的比較多,所以這些內(nèi)容會在動畫這部分講解。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內(nèi)容