溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

css-vars-ponyfill在ie環(huán)境下怎么用

發(fā)布時(shí)間:2021-03-18 13:39:41 來(lái)源:億速云 閱讀:253 作者:小新 欄目:web開(kāi)發(fā)

小編給大家分享一下css-vars-ponyfill在ie環(huán)境下怎么用,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!

css-vars-ponyfill

通過(guò)css變量來(lái)實(shí)現(xiàn)網(wǎng)頁(yè)換膚的過(guò)程中,會(huì)出現(xiàn)兼容性問(wèn)題。

css-vars-ponyfill在ie環(huán)境下怎么用 

為了解決ie,qq,百度瀏覽器等兼容性問(wèn)題,引入css-vars-ponyfill,但是在ie瀏覽器下,css-vars-ponyfill 的在nextjs下表現(xiàn)不佳,主要缺陷是由于頁(yè)面是服務(wù)端渲染,因此用戶在看到界面后,動(dòng)態(tài)主題色等樣式不能很快渲染好,而是有一個(gè)過(guò)渡的時(shí)間(css-vars-ponyfill 僅支持client-side),顏色會(huì)存在明顯替換的過(guò)程用戶體驗(yàn)差。通過(guò)閱讀 源碼 可以看到,cssVars需要等到瀏覽器contentLoaded之后,才會(huì)觸發(fā),否則一直監(jiān)聽(tīng)dom的data content事件,這就導(dǎo)致了體驗(yàn)上的問(wèn)題。

解決方案

1.解析速度

通過(guò)把直接去除 document.readyState !== 'loading' 這樣的限制條件使得瀏覽器在解析到,然后更改css-vars-ponyfill 的引入方式(舊的引入方式是在nextjs中的mainjs中引入module,然后直接調(diào)用cssVars(),這樣在調(diào)用到ponyfill的腳本前還會(huì)解析其他不相關(guān)的chunk,為了更快的解析css變量,需要手動(dòng)選擇插入位置),更改之后的css-vars-ponyfill 通過(guò)找到css變量的位置(nextjs 通過(guò)將不同組件下的style,統(tǒng)一打包在header里面),然后將更改后的ponyfill 插入到style 之后進(jìn)行調(diào)用,這一步選擇在服務(wù)端渲染的 _document.tsx 文件中更改。

2.解析穩(wěn)定性

通過(guò)手動(dòng)更改文件解析位置,以及對(duì)源碼的條件觸發(fā)機(jī)制進(jìn)行相關(guān)更改,首頁(yè)顏色渲染速度有了一定提升。但是仍存在一個(gè)問(wèn)題,即通過(guò)路由跳轉(zhuǎn)的界面,如果有新的style chunk,插入時(shí)不能進(jìn)行有效的css變量解析(已嘗試配置cssVars的option 打開(kāi)MutationObserver)。

因此,解決方案是通過(guò)判斷UA,來(lái)讓ie等瀏覽器下所有的路由通過(guò)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<boolean>(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()
      ) : (
        <Link {...props}>{children}</Link>
      )}
      <style jsx>{styles}</style>
    </>
  )
}

這里children的type 選擇了 ReactElement ,而不是插槽中通常支持的 ReactNode 主要是不想考慮直接插入字符串這種情況,會(huì)增加問(wèn)題的復(fù)雜度,因此直接在type這層做限制。還有Fragments 也沒(méi)有考慮,且沒(méi)有找到有效的Fragments 類(lèi)型,沒(méi)法在ReactNode 中把它Omit掉,nextjs 里面的Link 如果首層插入了Fragments 后,也無(wú)法正常跳轉(zhuǎn),可能原因也是無(wú)法再Fragments 上面綁定有效的事件吧,目前Fragments(16.13.1) 只支持key屬性,希望后續(xù)可以優(yōu)化。

看完了這篇文章,相信你對(duì)“css-vars-ponyfill在ie環(huán)境下怎么用”有了一定的了解,如果想了解更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI