vue2.0 transition -- demo實踐填坑

來源 | https://www.cnblogs.com/jr1993/p/vue.html
前言
實踐

.app.btnposition: fixedbottom: 50pxright: 10pxz-index: 10width: 50pxheight: 50pxline-height: 50pxborder-radius: 50%border: noneoutline: nonecolor: #ffffont-size: 18pxbackground: blue.menuposition: fixedbottom: 50pxright: 10pxwidth: 50pxheight: 50pxborder-radius: 50%transition: all .7s ease-in&.move-enter-active.innertransform: translate3d(0, 0, 0)transition-timing-function: cubic-bezier(0, .57, .44, 1.97).inner-1transition-delay: .1s.inner-2transition-delay: .2s.inner-3transition-delay: .3s&.move-enter, &.move-leave-active.innertransition-timing-function: ease-in-out.inner-1transform: translate3d(0, 60px, 0)transition-delay: .3s.inner-2transform: translate3d(40px, 40px, 0)transition-delay: .2s.inner-3transform: translate3d(60px, 0, 0)transition-delay: .1s.innerdisplay: inline-blockposition: absolutewidth: 30pxheight: 30pxline-height: 30pxborder-radius: 50%background: redtext-align: centercolor: #ffftransition: all .4s.inner-1top: -50pxleft: 10px.inner-2left: -30pxtop: -30px.inner-3left: -50pxtop: 10px
css 動畫--實踐
先來看看demo效果:

這個案例其實跟上面的demo差不多,不同之處在于過渡效果是使用css動畫來實現(xiàn),看下實現(xiàn)的代碼:
@keyframes shape-change {0%, 100% {border-radius: 50%background: red}50% {border-radius: 0background: blue}}@keyframes moveball-in {0% {transform: translate3d(300px,-200px,0)}50% {transform: translate3d(100px,-400px,0)}100% {transform: translate3d(0,0,0)}}@keyframes moveball-out {0% {transform: translate3d(0,0,0)}50% {transform: translate3d(100px,-400px,0)}100% {transform: translate3d(300px,-200px,0)}}.app.btnwidth: 40pxheight: 30pxmargin-top: 40pxborder: noneoutline: nonebackground: redcolor: #fff.ballposition: absolutebottom: 20pxleft: 20pxwidth: 50pxheight: 50pxtransition: all 1s cubic-bezier(.22,-0.86,.97,.58)&.move-enter-activeopacity: 1animation: moveball-in 1s.inneranimation: shape-change 1s&.move-leave-activeopacity: 0.8animation: moveball-out 1s.inneranimation: shape-change 1s.innerdisplay: inline-blockwidth: 30pxheight: 30pxborder-radius: 50%background: redtransition: all 1s linear
前兩個栗子都是有進(jìn)入和離開的過渡,但是如果一些場景只需要進(jìn)入過渡然后就結(jié)束了,那么這時就可以使用JavaScript鉤子結(jié)合CSS transitions/animations來實現(xiàn),當(dāng)然也可以單獨使用。

這個一個非常low的模擬炮彈發(fā)射的場景,可以看到小球有拋物線軌跡運動的過渡,而且發(fā)射出去就不會再回來了,那么這個demo就是使用了JavaScript鉤子結(jié)合css來實現(xiàn)的,接下來看下關(guān)鍵代碼:
首先,由于本身這個demo是一組元素的過渡,所以有些童鞋就會覺得用2.0提供的transition-group不就行了嘛。
不過transition-group是列表過渡,我的理解是那一組元素是相關(guān)聯(lián)的、互相影響的,但是這個demo的元素每個都是獨立的,只不過是一組獨立的元素過渡,所以還是用transition比較合理,那使用v-for就可以實現(xiàn)一組相同過渡的元素啦。接下來看JavaScript鉤子怎么實現(xiàn)這個過渡:
export default {data () {return {shells: [{show: false},{show: false},{show: false}]};},methods: {launch (event) {for (let i = 0; i < this.shells.length; i++) {let shell = this.shells[i];if (!shell.show) {shell.show = true;shell.target = event.target;return;}}},beforeEnter (el) {let count = this.shells.length;while (count--) {let shell = this.shells[count];if (shell.show) {let rect = shell.target.getBoundingClientRect();let left = rect.left - 32;let top = -(window.innerHeight - rect.top - 15);el.style.display = '';el.style.webkitTransform = `translate3d(0,${top}px,0)`;el.style.transform = `translate3d(0,${top}px,0)`;let inner = el.getElementsByClassName('inner')[0];inner.style.webkitTransform = `translate3d(${left}px,0,0)`;inner.style.transform = `translate3d(${left}px,0,0)`;}}},enter (el, done) {/* eslint-disable no-unused-vars */let refresh = el.offsetHeight;this.$nextTick(() => {el.style.webkitTransform = 'translate3d(0,0,0)';el.style.transform = 'translate3d(0,0,0)';let inner = el.getElementsByClassName('inner')[0];inner.style.webkitTransform = 'translate3d(0,0,0)';inner.style.transform = 'translate3d(0,0,0)';});done();},afterEnter (el) {let ball = this.shells[0];ball.show = false;el.style.display = 'none';}}};
過渡元素就不需要為其添加vue的過渡css類名了,只需在元素本身添加transition即可,那vue在之前css過渡的時候會自動幫我們?nèi)ヌ砑訉?yīng)的類名來完成過渡效果,但是用javascript鉤子就需要我們自己完成這個始末狀態(tài)的設(shè)置了。
當(dāng)我們點擊觸發(fā)一個過渡的時候,我們在beforeEnter里先拿到當(dāng)前元素的偏移位置,然后給過渡元素設(shè)置其起始位置,在enter里需要重新觸發(fā)下瀏覽器的重繪,然后在下一幀重新設(shè)置元素的結(jié)束位置,這時就會產(chǎn)生過渡效果,在過渡完成后我們將當(dāng)前元素隱藏即可。
那剛才講到的列表過渡,接下來就是關(guān)于使用transition-group的一個小demo了。
transition-group -- 實踐
先看下demo效果:

其實就是個簡單的todo lists的小demo,可以看到,當(dāng)其中一個元素過渡的時候,會影響其他元素的過渡。
當(dāng)然,刪除按鈕其實本身也是一個transition過渡,也就是說可以在transition-group里使用transition,看下相關(guān)代碼:
{{item.text}}
有個小坑的地方就是,之前看官網(wǎng)列表過渡的栗子,它是一個數(shù)組,元素都是數(shù)字,并且每一項都必須設(shè)置唯一的key值。
所以我完成demo的時候就自作聰明地將索引值傳給key,結(jié)果過渡老是不對,后來換成對應(yīng)的item就正常了(生無可戀臉)。
這個demo用到了vue-touch,雖然github上說不支持2.0版本了,但是有一個next分支是支持的,只需在項目下安裝它即可:
sudo npm install --save git://github.com/vuejs/vue-touch.git#next這里看下主要的樣式:
.listdisplay: flexwidth: 100%height: 40pxline-height: 40pxmargin-bottom: 10pxcolor: #666font-size: 14pxbackground: #eeetransition: all .4s&.slide-movetransition: transform 1s&.slide-entertransform: translate3d(-100%, 0, 0)&.slide-leave-activeposition: absolutetransform: translate3d(-100%, 0, 0)&:last-childmargin-bottom: 0.del-btnflex: 0 0 60pxborder: noneoutline: nonecolor: #fffbackground: redtransition: all .4s&.move-enter, &.move-leave-activetransform: translate3d(70px, 0, 0).textflex: 1padding-left: 20px
如果改變定位過渡的duration與進(jìn)入離開一樣的話,其實可以不用-move,這里設(shè)置-move的過渡的duration不同于元素進(jìn)入離開的duration產(chǎn)生一種速度差,看起來舒服點。而且-leave-active需要設(shè)置position: absolute才會有效果。現(xiàn)在看來其實列表過渡也是很容易實現(xiàn)的。
最后
其實vue2.0過渡系統(tǒng)還提供了其他場景的過渡應(yīng)用,這里就不展開贅述了。引用官網(wǎng)文檔的一句話:唯一的限制是你的想象力。哈哈...

