”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 让我们创建一个简单的 React hook 来检测浏览器及其功能

让我们创建一个简单的 React hook 来检测浏览器及其功能

发布于2024-11-08
浏览:673

Let

用户代理嗅探是最流行的浏览器检测方法。不幸的是,由于多种原因,前端开发不太容易使用它。浏览器供应商不断尝试让嗅探变得不可能。因此,每个浏览器都有自己的用户代理字符串格式,解析起来非常复杂。

有一种更简单的方法可以使用浏览器 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检测用户浏览器支持情况

为了检测用户浏览器,我们必须进行一些黑客攻击。

浏览器黑客攻击与违法行为无关。它只是一个特殊的 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() 更容易维护,而且更细粒度。它欢迎开发人员使用优雅降级或渐进增强方法并精细地应用补丁。

版本声明 本文转载于:https://dev.to/morewings/lets-create-a-simple-react-hook-to-detect-browsers-and-their-capabilities-4lnf?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何协调 Ed25519 的 Golang 和 Bittorrent 私钥格式之间的差异?
    如何协调 Ed25519 的 Golang 和 Bittorrent 私钥格式之间的差异?
    ed25519.Public Result Discrepancy问题是由 ed25519 私钥的不同格式引起的。密钥以 32 字节种子开始,使用 SHA512 进行哈希处理以创建 64 字节(在此过程中某些位会翻转)。Golang 私钥格式 Golang 私钥格式由 32 字节种子与 32 字节公...
    编程 发布于2024-11-08
  • 向您的 Go API 添加 API 速率限制
    向您的 Go API 添加 API 速率限制
    好吧,伙计们,到目前为止我们已经介绍了很多内容:JWT 身份验证、数据库连接、日志记录和错误处理。但是,当您的 API 开始受到请求的冲击时会发生什么?如果没有控制,高流量可能会导致响应时间缓慢甚至停机。 ? 本周,我们将通过实施速率限制来控制流量来解决这个问题。我们将使用简单有效的 golang....
    编程 发布于2024-11-08
  • 除了“if”语句之外:还有哪些地方可以在不进行强制转换的情况下使用具有显式“bool”转换的类型?
    除了“if”语句之外:还有哪些地方可以在不进行强制转换的情况下使用具有显式“bool”转换的类型?
    无需强制转换即可上下文转换为 bool您的类定义了对 bool 的显式转换,使您能够在条件语句中直接使用其实例“t”。然而,这种显式转换提出了一个问题:“t”在哪里可以在不进行强制转换的情况下用作 bool?上下文转换场景C 标准指定了四种值可以根据上下文转换为的主要场景bool:语句:if、whi...
    编程 发布于2024-11-08
  • 我使用 Snowflake (SiS) 中的 Streamlit 制作了一个令牌计数检查应用程序
    我使用 Snowflake (SiS) 中的 Streamlit 制作了一个令牌计数检查应用程序
    介绍 您好,我是 Snowflake 的销售工程师。我想通过各种帖子与大家分享我的一些经验和实验。在本文中,我将向您展示如何使用 Snowflake 中的 Streamlit 创建应用程序来检查令牌计数并估算 Cortex LLM 的成本。 注:本文仅代表个人观点,不代表Snowf...
    编程 发布于2024-11-08
  • 如何修复 MySQL 中的“标头和客户端库次要版本不匹配”?
    如何修复 MySQL 中的“标头和客户端库次要版本不匹配”?
    标头版本不匹配:解决困境简介通常在数据库连接的上下文中遇到,错误消息“标头和客户端库次要”版本不匹配”表示MySQL头的版本和客户端库的版本之间存在差异。这种差异可能会阻碍与数据库建立正确的连接。原因和解决方案1。 PHP 和 MySQL 版本不兼容确保 PHP 和 MySQL 版本兼容。 PHP ...
    编程 发布于2024-11-08
  • 你可能不需要 monorepo
    你可能不需要 monorepo
    如果你在同一个“monorepo”中有多个 npm 包,如果这是一个大而连贯的包,你和你的用户可能会过得更好。 许多簿记和管理任务就消失了。 三次摇动都会删除未使用的代码。 每个包之间的不健康依赖关系是不可能的,因为一切都只是一个依赖关系。 不要考虑“monorepo”,而是考虑一个整体。也就是说,...
    编程 发布于2024-11-08
  • 如何在 PHP 中使用 cURL 建立持久的 HTTP 连接?
    如何在 PHP 中使用 cURL 建立持久的 HTTP 连接?
    如何在 PHP 中使用 cURL 实现持久 HTTP 连接?在 PHP 中使用 cURL 库进行 HTTP 请求时,由于以下原因,网络接口上可能会出现高中断率:连接开口过多。当向外部 API 或数据库服务器发出大量请求时,这一点尤其明显。要解决此问题,了解 cURL 是否支持持久连接以及如何利用它们...
    编程 发布于2024-11-08
  • 什么时候应该使用 Tkinter Entry 的 Get 函数来检索用户输入?
    什么时候应该使用 Tkinter Entry 的 Get 函数来检索用户输入?
    Tkinter Entry 的 get 功能:了解用法和计时在 Tkinter 中,Entry 小部件允许用户提供文本输入。为了检索该输入,通常使用 get() 函数。然而,如果过早调用 get() 函数,可能会出现意外行为。获取输入:计时很重要提供的示例代码的问题是 get () 函数在 GUI ...
    编程 发布于2024-11-08
  • Java Spring Boot使用登录gradle项目
    Java Spring Boot使用登录gradle项目
    这里的动机是我花了太多时间试图弄清楚如何在 gradle 中的 spring boot 中使用 log4j 添加日志记录。这里的 gradle 部分是给我最痛苦的部分,因为我能找到的所有文档都是针对 maven 的。 因此,我在这里记录我的发现,以便下一个正在寻找此内容的人可以找到我的帖子并能够快速...
    编程 发布于2024-11-08
  • 使用 Twig 通过 PHP 渲染 Markdown
    使用 Twig 通过 PHP 渲染 Markdown
    Twig 是使用 Symfony 开发 Web 应用程序时渲染 HTML 的首选模板引擎。 然而,Twig 的灵活性不仅仅限于生成 HTML 页面。它可以成为跨多个渠道交付内容的强大工具,例如生成 Markdown 文件、JSON 输出,甚至纯文本,所有这些都来自同一组内容。 这种适应性允许您为不同...
    编程 发布于2024-11-08
  • 以下是一些标题选项,请记住问题格式的需要:

**专注于挑战:**

* **如何使用 AST 以编程方式修改 Python 源代码?**
* **什么工具Ena
    以下是一些标题选项,请记住问题格式的需要: **专注于挑战:** * **如何使用 AST 以编程方式修改 Python 源代码?** * **什么工具Ena
    Python 源代码修改的 AST 操作以编程方式编辑 Python 源代码通常涉及读取代码并将其解析为抽象语法树 (AST)。然而,修改 AST 并写回修改后的代码以生成新的源文件对于像 ast 和编译器这样的标准 Python 模块来说可能具有挑战性。lib2to3 库提供了解决此问题的一个方法...
    编程 发布于2024-11-08
  • 如何解决 PHP CURL CURLOPT_SSL_VERIFYPEER 中的“SSL CA 证书问题”错误?
    如何解决 PHP CURL CURLOPT_SSL_VERIFYPEER 中的“SSL CA 证书问题”错误?
    PHP CURL CURLOPT_SSL_VERIFYPEER:解决证书验证问题尽管努力使用 CURLOPT_SSL_VERIFYPEER 禁用 SSL 证书验证,但某些用户还是遇到了错误:“在执行 CURL 请求时,SSL CA 证书出现问题(路径?访问权限?)” PHP.解决问题要解决此问题,必...
    编程 发布于2024-11-08
  • 使用 JavaScript 进行函数式编程
    使用 JavaScript 进行函数式编程
    JavaScript 中的函数式编程是什么? F函数式编程是最近流行的一种范式,因为它允许您编写更加模块化、可重用且易于维护的代码。函数式编程是一种依赖于两个主要概念的编程范例。 首先,代码以函数的形式编写,对数据进行操作,不改变任何参数。不会修改现有数据,而是创建新数据。 其次,...
    编程 发布于2024-11-08
  • MySQL 中 INSERT 语句的最大大小是多少?
    MySQL 中 INSERT 语句的最大大小是多少?
    MySQL INSERT 语句中的查询大小限制在 MySQL 中执行 INSERT 语句时,考虑潜在的大小限制至关重要。本文探讨了决定单个 INSERT 语句中可以包含的最大行数和字节数的因素。行计数限制MySQL 不强制执行限制可以使用“INSERT ... SELECT”模式插入的行数。假设源数...
    编程 发布于2024-11-08
  • 如何从原始列表中每第 N 个项目生成一个新列表?
    如何从原始列表中每第 N 个项目生成一个新列表?
    用原始列表中的每 N 个项目创建一个列表在数据分析或编程中,通常需要使用一个清单。一项常见任务是创建一个仅包含原始列表中每第 N 个项目的新列表。例如,给定一个从 0 到 1000 的整数列表,我们如何获得一个仅包含第一个和后续第 10 个项目的列表?使用传统的 for 循环,我们可以按如下方式完成...
    编程 发布于2024-11-08

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3