小編給大家分享一下css-vars-ponyfill在ie環(huán)境下怎么用,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
創(chuàng)新新互聯(lián),憑借十年的網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)經(jīng)驗(yàn),本著真心·誠心服務(wù)的企業(yè)理念服務(wù)于成都中小企業(yè)設(shè)計(jì)網(wǎng)站有上千多家案例。做網(wǎng)站建設(shè),選創(chuàng)新互聯(lián)公司。
css-vars-ponyfill
通過css變量來實(shí)現(xiàn)網(wǎng)頁換膚的過程中,會出現(xiàn)兼容性問題。
為了解決ie,qq,百度瀏覽器等兼容性問題,引入css-vars-ponyfill,但是在ie瀏覽器下,css-vars-ponyfill 的在nextjs下表現(xiàn)不佳,主要缺陷是由于頁面是服務(wù)端渲染,因此用戶在看到界面后,動(dòng)態(tài)主題色等樣式不能很快渲染好,而是有一個(gè)過渡的時(shí)間(css-vars-ponyfill 僅支持client-side),顏色會存在明顯替換的過程用戶體驗(yàn)差。通過閱讀 源碼 可以看到,cssVars需要等到瀏覽器contentLoaded之后,才會觸發(fā),否則一直監(jiān)聽dom的data content事件,這就導(dǎo)致了體驗(yàn)上的問題。
解決方案
1.解析速度
通過把直接去除 document.readyState !== 'loading'
這樣的限制條件使得瀏覽器在解析到,然后更改css-vars-ponyfill 的引入方式(舊的引入方式是在nextjs中的mainjs中引入module,然后直接調(diào)用cssVars(),這樣在調(diào)用到ponyfill的腳本前還會解析其他不相關(guān)的chunk,為了更快的解析css變量,需要手動(dòng)選擇插入位置),更改之后的css-vars-ponyfill 通過找到css變量的位置(nextjs 通過將不同組件下的style,統(tǒng)一打包在header里面),然后將更改后的ponyfill 插入到style 之后進(jìn)行調(diào)用,這一步選擇在服務(wù)端渲染的 _document.tsx文件中更改。
2.解析穩(wěn)定性
通過手動(dòng)更改文件解析位置,以及對源碼的條件觸發(fā)機(jī)制進(jìn)行相關(guān)更改,首頁顏色渲染速度有了一定提升。但是仍存在一個(gè)問題,即通過路由跳轉(zhuǎn)的界面,如果有新的style chunk,插入時(shí)不能進(jìn)行有效的css變量解析(已嘗試配置cssVars的option 打開MutationObserver)。
因此,解決方案是通過判斷UA,來讓ie等瀏覽器下所有的路由通過a標(biāo)簽跳轉(zhuǎn),觸發(fā)css-ponyfill的重新解析執(zhí)行。
export function browser() { const UA = window.navigator.userAgent if (UA.includes("qqbrowser")) return "qqbrowser" if (UA.includes("baidu")) return "baidu" if (UA.includes("Opera")) return "Opera" if (UA.includes("Edge")) return "Edge" if (UA.includes("MSIE") || (UA.includes("Trident") && UA.includes("rv:11.0"))) return "IE" if (UA.includes("Firefox")) return "Firefox" if (UA.includes("Chrome")) return "Chrome" if (UA.includes("Safari")) return "Safari" }
type CommonLinkProps = { children: ReactElement href?: string target?: string outerLink?: boolean styles?: unknown } export default function CustomLink(props: CommonLinkProps) { const { children, href, target, as, outerLink, styles = emptyStyles } = props const [isIE, setIE] = useState(false) const cloneEl = (c: ReactElement, props?: any) => React.cloneElement(c, { href: as ?? href, target, ...props }) useEffect(() => { if (["IE", "qqbrowser", "baidu"].includes(browser())) { setIE(true) } }, []) function renderLink() { if (Children.only(children).type === "a") { const node = cloneEl(children as ReactElement) return node } else { let fn: () => void | null = null if (outerLink) { fn = () => { window.open(as ?? href) } } else { fn = () => { window.location.href = as ?? href } } const node = cloneEl(children as ReactElement, { onClick: () => { fn() }, }) return node } } return ( <> {!href ? ( children ) : isIE ? ( renderLink() ) : ( {children} )} > ) }
這里children的type 選擇了 ReactElement
,而不是插槽中通常支持的 ReactNode
主要是不想考慮直接插入字符串這種情況,會增加問題的復(fù)雜度,因此直接在type這層做限制。還有Fragments 也沒有考慮,且沒有找到有效的Fragments 類型,沒法在ReactNode 中把它Omit掉,nextjs 里面的Link 如果首層插入了Fragments 后,也無法正常跳轉(zhuǎn),可能原因也是無法再Fragments 上面綁定有效的事件吧,目前Fragments(16.13.1) 只支持key屬性,希望后續(xù)可以優(yōu)化。
看完了這篇文章,相信你對“css-vars-ponyfill在ie環(huán)境下怎么用”有了一定的了解,如果想了解更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!