使用者代理嗅探是最受歡迎的瀏覽器偵測方法。不幸的是,由於多種原因,前端開發不太容易使用它。瀏覽器供應商不斷嘗試讓嗅探變得不可能。因此,每個瀏覽器都有自己的使用者代理字串格式,解析起來非常複雜。
有一個更簡單的方法可以使用瀏覽器 CSS API 實現相同的目的,我將向您展示。那麼讓我們建立瀏覽器功能檢測 React hook。
我們將使用 CSS.supports() 靜態方法。它會傳回一個布林值,指示瀏覽器是否支援給定的 CSS 功能。這是 @supports at-rule 的 javascript 模擬。它的工作原理與媒體查詢類似,但以 CSS 功能為主題。
在元件渲染週期中呼叫 CSS.supports() 最簡單的方法會在伺服器端渲染環境(例如 Next.js)中產生問題。因為伺服器端渲染器無法存取瀏覽器 API,所以它只是產生一串程式碼。
import type {FC} from 'react'; const Component: FC = () => { // ? Don't do this! const hasFeature = CSS.supports('your-css-declaration'); // ... }
我們將使用這個簡單的鉤子。這個鉤子接收一個包含support條件的字串,這是我們要驗證的CSS規則,例如顯示:彎曲。
import {useState, useEffect} from 'react'; export const useSupports = (supportCondition: string) => { // Create a state to store declaration check result const [checkResult, setCheckResult] = useState(); useEffect(() => { // Run check as a side effect, on user side only setCheckResult(CSS.supports(supportCondition)); }, [supportCondition]); return checkResult; };
現在我們可以從 React 元件內部檢查不同的 CSS 功能支援。這是 MDN @supports 參考
import type {FC} from 'react'; const Component: FC = () => { // Check for native `transform-style: preserve` support const hasNativeTransformSupport = useSupports(' (transform-style: preserve) '); // Check for vendor prefixed `transform-style: preserve` support const hasNativeTransformSupport = useSupports(' (-moz-transform-style: preserve) or (-webkit-transform-style: preserve) '); // ... }
為了偵測使用者瀏覽器,我們必須進行一些駭客攻擊。
瀏覽器駭客攻擊與違法行為無關。它只是一個特殊的 CSS 聲明或選擇器,在可用瀏覽器之一中的工作方式有所不同。
這是包含各種瀏覽器駭客的參考頁。在我的機器上進行徹底的實驗後,我選擇了這些:
const hacksMapping = { // anything -moz will work, I assume firefox: '-moz-appearance:none', safari: '-webkit-hyphens:none', // tough one because Webkit and Blink are relatives chrome: ' not (-webkit-hyphens:none)) and (not (-moz-appearance:none)) and (list-style-type:"*"' }
這是我們最終的鉤子:
export const useDetectBrowser = () => { const isFirefox = useSupports(hacksMapping.firefox); const isChrome = useSupports(hacksMapping.chrome); const isSafari = useSupports(hacksMapping.safari); return [ {browser: 'firefox', condition: isFirefox}, {browser: 'chromium based', condition: isChrome}, {browser: 'safari', condition: isSafari}, ].find(({condition}) => condition)?.browser as 'firefox' | 'chromium based' | 'safari' | undefined; };
這是該鉤子的完整工作演示。
我不能說這是一種萬無一失、穩定的方法。瀏覽器經常更新,供應商屬性經常被放棄或被標準取代。同時,我可以說一下用戶代理嗅探。兩種方式都有類似的問題。但 CSS.contains() 更容易維護,而且更細粒度。它歡迎開發人員使用優雅降級或漸進增強方法並精細地應用補丁。
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3