大家好,我是奶綠茶,今天來聊聊 vue 裡的 transition-group

先來看一下官方的範例:
https://vuejs.org/examples/#list-transition

在 v-for 的外層新增一個 TransitionGroup Component,當元素新增或刪除時,就可以有動態效果,簡單又好用。

當新增元素時,下方的元素會有個往下移的態動效果,單看 CSS 的部份,
怎麼想都不可能只用純 CSS 就做到。

還好官網的範例給了一個重要的連結。

FLIP list transitions with the built-in <TransitionGroup>.
https://aerotwist.com/blog/flip-your-animations/

然後再去翻 vue 的原始碼,就可以看到 TransitionGroup 就是使用上方的 FLIP 手法。
https://github.com/vuejs/core/blob/main/packages/runtime-dom/src/components/TransitionGroup.ts

FLIP 指的是 First, Last, Invert, Play 這四個 Step,因為如果直接對 DOM 更改元素的位置和大小,會觸發 Browser 的 Layout 改變,
這部份可以參考 https://csstriggers.com/ ,查看那些屬性會執行更多的運算。

先講結論,CSS 的動態要優先採用 transform,參考 csstriggers ,就會發現該屬性只會發生 Compositing。

而 FLIP 就是採用這樣的特性,把可預期的最終位置先算出來,再使用 transfrom 來做到效果,讓效能提升,而 vue TransitionGroup 也是採用這樣的方法。

附上奶綠測試的版本,祝大家學習愉快
https://jsbin.com/rufopeg/4/edit?html,css,js,output

參考文章:
https://ithelp.ithome.com.tw/articles/10249554
https://blog.techbridge.cc/2018/10/20/flip-your-animation/
https://aerotwist.com/blog/flip-your-animations/

--

--

大家好,我是奶綠茶

為了要優化 React render,有時會在 useState 初始化時就判斷值。

const [device, setDevice] = React.useState(()=> {
return window.innerWidth < 768 ? 'mobile' : 'desktop';
});
React.useEffect(()=> {
const resizeHandler = () => {
setDevice(window.innerWidth < 768 ? 'mobile' : 'desktop');
}
resizeHandler();
window.addEventListener('resize', resizeHandler);
return () => {
window.removeEventListener('resize', resizeHandler);
}
}, []);

這樣的優點是進到 useEffect 再判斷時,會因為 setDevice 是相同的字串,就可以減少一次 render 。

但這段 Code 進到 nextjs SSR 時就會有異想不到的結果,因為 Server 端沒有 window, 所以把 code 小改一下

const [device, setDevice] = React.useState(()=> {
if(!process.browser) {
return 'mobile';
}
return window.innerWidth < 768 ? 'mobile' : 'desktop';
});

Server 一率拿 ‘mobile’,而 useEffect 又只會在 client 執行,經過計算,可以拿到正確的結果。
But, 人生就是這個 But, 我們把 device 字串 render 出來
並一開始進站時,先把畫面拉大成桌機。

return (
<div data-device={device} className={'div-'+device}>
Hello World.{device}
</div>
)

看一下 render 出來的結果,會發現 DOM 裡的文字是正確的 desktop,但 class 和 attr 卻顯示 Server 的 mobile 字串

看來和 window 相關的還是統一在 client 端處理是比較好的

附上測試用的 Code, 祝大家學習愉快。

https://codesandbox.io/s/nextjs-ssr-issue-forked-s3ehk

--

--