最近有個需求,一個列表上下移動要有簡單過渡效果,在網上找了找沒找到,多是我搜的關鍵詞不對?vue
試了試 Vue 的transition-group
,也沒有達到預期的效果,而後就花了點時間作了一個操做Demo。git
在線演示:jsrun.net/hdyKpgithub
Demo源碼:github.com/thinkupp/vu…bash
某列的數據由 X 位置上升到 Y 位置的過渡效果動畫
這個過渡效果一共由三部分組成:ui
Y行
位置插入X行
位置的數據,添加一個高度展開效果,並使該行的數據不可見X行
數據不可見, 並添加一個高度收起效果X行
的DOM, 設置爲固定定位fixed
, top
取X行距離body
的位置(offsetTop
), 並作一個向上移動效果到Y行
位置這裏僅僅依靠`offsetTop`並不許確,具體見文章後面的內容. url
來看一個放慢版的效果,加了個邊框而且沒有設置visibility
屬性,看的會更明瞭:spa
簡單說一下。.net
第一部分描述一個讓目標位置底下全部行有一個向下移動的過程。3d
第二部分描述那個移動的行消失的過程。
第三部分描述一個移動的過程。
爲了避免污染數據渲染出來的視圖,除了固定定位的那個盒子是直接操做DOM,以外的兩個效果是經過操做數據+類名實現的。
緣由:因爲 v-for 的時候給每行的key
是index
,數據源發生變化後會致使受影響的元素的index
也發生改變。
解決:將key
的值由index
更換爲item
(惟一值, 在這裏item
指的是圖片url) 。
當位置頻繁改變的時候要清除上一次的動畫遺留元素,否則元素會發生各類錯亂,這個很容易想的到,錯誤演示就不錄了,看一下完成的效果。
緣由:第一部分插入X行
數據形成,由於兩條相同的數據重複的item
會形成重複的key
。
解決:在進行第一部分的時候將原來那一行的key
改成其它值。
<li :key="closeIndex === index ? Date.now() : item"></li>
複製代碼
我用的時間戳,其實理論上來說只要能保持惟一寫什麼均可以,反正這一行數據將在動畫結束後從數據中刪除。
僅僅依靠offsetTop
計算位置是不許確的,當頁面發生滾動後元素與Body的實際距離就不是offsetTop
的值了。應該用offsetTop
減去scrollTop
,這樣纔是元素當前與Body的實際距離。
/*
* 計算盒子當前距離body的距離
* @param {HTMLElement} ele 要計算位置的盒子
* @returns {number} 當前位置距離body的距離
* */
calcTop(ele) {
let offsetTop = ele.offsetTop;
let offsetParent = ele.offsetParent;
while (offsetParent) {
offsetTop += offsetParent.offsetTop;
offsetParent = offsetParent.offsetParent;
}
return offsetTop - (document.body.scrollTop || document.documentElement.scrollTop)
}
複製代碼
獲取 scrollTop 的方式根據項目不一樣也不一樣,並非全部的狀況下均可以經過 document.body.scrollTop || document.documentElement.scrollTop 獲取到正確的內容,具體區分項目
描述有點亂,但願能給也遇到此問題的朋友提供一個思路,有誤的地方麻煩你們及時指正。