一行代碼實現(xiàn)display"過渡動畫"原理
寫本文的起因
上篇文章,提到如何讓display出現(xiàn)過渡動畫,卻沒有仔細介紹原理。 為了更好的讓想學習的人深入理解于是加班加點寫下了這篇“短文”,我想以后還是以短文為主,不然大家看起來太累
正式開始
初始化界面
"en">
????"UTF-8">
????"viewport"?content="width=device-width,?initial-scale=1.0">
????Document
????
????"app">
????
????

此時我將app的display初始化為none,并且寫入腳本文件
????。。。
初始化界面變成了這樣:

此時,我點擊測試按鈕

并沒有出現(xiàn)動畫,非常生硬的出來了,有一些場景我又要性能,比如初始化不渲染,但是當它出現(xiàn)又要有動畫的時候,就有可能使用這行代碼
?test.onclick?=?function?()?{
????????const?app?=?document.querySelector('#app')
????????console.log(app,?'app')
????????app.style.display?=?"block"
????????const?height?=?app.offsetHeight
????????app.style.transform?=?"translateX(200px)"
????}
當我加入const height = app.offsetHeight這行代碼的時候,再點擊測試按鈕,display切換就順帶出來了“動畫”,有了過度效果 為什么會出現(xiàn)動畫了呢?因為我讀取dom的這些特殊屬性時,瀏覽器就會強制清空渲染隊列一次,讓我拿到最新的值。也就是說讀取的時候,其實已經(jīng)是display為"block"了,因此。我們出現(xiàn)了過渡動畫
效果如下所示:

出現(xiàn)“過渡動畫”是什么情況?
其實 display是不能出現(xiàn)動畫的,所以標題+了引號怎么才能有過渡? 有數(shù)字的變化,例如透明度,從 0-1.初始化有渲染展示的 在 transition里面包含的屬性...等 大家可以補充
為什么加了一行代碼后,就能出現(xiàn)動畫了?
大家在寫現(xiàn)代前端框架,遇到最多的問題就是渲染的時期不確定的問題。 例如 vue里面的nextTick實現(xiàn),有一個優(yōu)雅降級的實現(xiàn)。它在mounted生命周期函數(shù)里面去獲取dom節(jié)點時候,經(jīng)常獲取不到或者獲取不到完整渲染的dom節(jié)點。(我很久沒有使用vue了,有問題可以補充),為什么?像現(xiàn)在數(shù)據(jù)驅動的框架,只要數(shù)據(jù)改變了,對應邏輯綁定了數(shù)據(jù)的 dom節(jié)點按道理應該更新,可是更新時機是我們無法確定的,因為這中間有中間層,比如存在diff算法計算過程,可能存在隊列,因為當你頻繁修改數(shù)據(jù)的時候,框架本身要做優(yōu)化,合并一段時間的數(shù)據(jù)更新再去真正更新dom,等這些事情都做完了,才能去更新dom節(jié)點,然后我們才能看到最新數(shù)據(jù)對應的節(jié)點當我們真的要去更新 dom節(jié)點的時候,也存在一個隊列。這個就是瀏覽器的渲染隊列如果你無法理解我上面說的,可以看我之前手寫 React系列文章中的setState異步隊列實現(xiàn)
瀏覽器的渲染隊列
什么時候最能體現(xiàn)這個隊列的作用? 頻繁直接操作 dom時候,例如for循環(huán)里面頻繁操作dom,這個時候瀏覽器就會優(yōu)化我們的操作,合并一部分操作一次性執(zhí)行渲染隊列跟 display的關聯(lián)
當我們執(zhí)行了 app.style.display = "block"這行代碼時候,dom節(jié)點此時并沒有更新,js解析引擎是聰明的,它發(fā)現(xiàn)你后面馬上有代碼要修改dom節(jié)點,會先存入隊列中集中一次性操作當我們執(zhí)行了 app.offsetHeight這行代碼時候,發(fā)現(xiàn)我們需要讀取dom節(jié)點的屬性,瀏覽器害怕現(xiàn)在隊列中沒有執(zhí)行的操作會讓你讀取到不正確的值引發(fā)BUG,于是就會清空渲染隊列并且執(zhí)行,讓你拿到最精確/新的值
當你請求向瀏覽器請求一些 style信息的時候,就會讓瀏覽器flush隊列,比如:offsetTop, offsetLeft, offsetWidth, offsetHeightscrollTop/Left/Width/HeightclientTop/Left/Width/Heightwidth,height當你請求上面的一些屬性的時候,瀏覽器為了給你最精確的值,需要 flush隊列,因為隊列中可能會有影響到這些值的操作。即使你獲取元素的布局和樣式信息跟最近發(fā)生或改變的布局信息無關, 瀏覽器都會強行刷新渲染隊列。
清空渲染隊列后
當讀取 offsetHeight屬性后,我們清空了渲染隊列,那么此時dom重新渲染完成后,此時display已經(jīng)是block了。而且展示在界面上面了,我們再操作dom屬性就會出現(xiàn)過渡動畫了。
最后
紙上得來終覺淺,多實踐、多思考是走向更高級別必經(jīng)之路,想要看我之前手寫源碼文章的,我的gitHub源碼地址是:
https://github.com/JinJieTan/Peter-,記得Star哦
掃碼關注公眾號,訂閱更多精彩內容。
“在看和轉發(fā)”就是最大的支持
評論
圖片
表情
