問題
聊天頁面的表情面板,滑動效果使用了ant design mobile的Swiper。
原代碼中,Swiper 組件在 isShow 為 false 時渲染的是 <></>(空元素),控制臺警告Swiper
needs at least one child,Swiper.Item 需要一個默認的內容,不能直接為空。
<Swiper>{isShow ? emojiPages.map((page, pageIndex) => (<Swiper.Item key={pageIndex}><Grid columns={7} gap={8}>{page.map((item, index) => (<Grid.Itemkey={index}onClick={() => setContent(content + item.text)}><div style={{textAlign: 'center'}}>{item.text}</div></Grid.Item>))}</Grid></Swiper.Item>)) : <></>}
</Swiper>
問題分析
通過判斷 emojiPages.length > 0 來確保只有在有表情數據時才渲染 Swiper.Item,避免 Swiper 組件沒有子元素的警告。
這個警告是因為 Swiper
組件在 isShow === false
時仍然在渲染,但沒有子元素,而 antd-mobile
需要至少一個 Swiper.Item
作為子元素,否則會報錯。
解決方案
方法1. 提供一個空 Swiper.Item
作為占位
在 isShow === false
時,仍然渲染 Swiper.Item
,但讓它保持空白:
<Swiper style={{ display: isShow ? 'block' : 'none' }}>{emojiPages.length > 0 ? (emojiPages.map((page, pageIndex) => (<Swiper.Item key={pageIndex}><Grid columns={7} gap={8}>{page.map((item, index) => (<Grid.Itemkey={index}onClick={() => setContent(prev => prev + item.text)}><div style={{ textAlign: 'center' }}>{item.text}</div></Grid.Item>))}</Grid></Swiper.Item>))) : (// ?? 這里添加一個空的 `Swiper.Item` 避免警告<Swiper.Item key="placeholder"><div style={{ height: 0, visibility: 'hidden' }}></div></Swiper.Item>)}
</Swiper>
方法2. 完全不渲染 Swiper
如果不想讓 Swiper
組件在 isShow === false
時渲染,可以用 條件渲染:
{isShow && emojiPages.length > 0 && (<Swiper>{emojiPages.map((page, pageIndex) => (<Swiper.Item key={pageIndex}><Grid columns={7} gap={8}>{page.map((item, index) => (<Grid.Itemkey={index}onClick={() => setContent(prev => prev + item.text)}><div style={{ textAlign: 'center' }}>{item.text}</div></Grid.Item>))}</Grid></Swiper.Item>))}</Swiper>
)}
- 方法 1:提供一個占位的
Swiper.Item
,讓Swiper
始終存在,但不會報錯。 - 方法 2:在
isShow === false
時,完全不渲染Swiper
,但可能會導致Swiper
重新初始化。
思考
方法 1(推薦):提供一個占位的 Swiper.Item
-
優點:
- 性能優化:
Swiper
組件始終存在,不會被頻繁銷毀和重新初始化,避免了組件狀態的重置和性能損耗。 - 用戶體驗:切換表情面板時不會發生過渡或初始化的閃爍,保持了流暢的交互體驗。
- 避免報錯:通過占位的
Swiper.Item
,確保Swiper
始終有子元素,避免了警告或錯誤。
- 性能優化:
-
缺點:
- 會占用一些不必要的空間,即使表情面板不顯示。
方法 2:在 isShow === false
時,完全不渲染 Swiper
-
優點:
- 避免占用空間:當不顯示表情面板時,完全不渲染
Swiper
,節省了頁面的布局空間。 - 簡潔:如果你希望
Swiper
只在需要時出現,這種方式比較直接。
- 避免占用空間:當不顯示表情面板時,完全不渲染
-
缺點:
- 性能問題:如果切換
isShow
狀態頻繁,會導致Swiper
組件重新初始化,這可能會影響性能,尤其是在復雜的表情面板或較大頁面的情況下。 - 重新渲染問題:有時候切換過程中可能會導致
Swiper
狀態不一致或初始化問題。
- 性能問題:如果切換
總結:
- 如果你的表情面板是一個經常切換的功能(比如用戶頻繁開關表情面板),建議使用 方法 1。這樣避免了
Swiper
的頻繁銷毀和初始化,能保證更流暢的用戶體驗。 - 如果你對性能要求較高,并且表情面板的切換并不頻繁,或者你希望完全控制其占用空間,可以選擇 方法 2。
個人推薦方法 1,因為它能保持組件的穩定性和流暢的交互體驗,特別是在切換時不需要重新加載內容。