ReactJS:如何确定应用程序是在移动浏览器还是桌面浏览器上查看

Posted

技术标签:

【中文标题】ReactJS:如何确定应用程序是在移动浏览器还是桌面浏览器上查看【英文标题】:ReactJS: How to determine if the application is being viewed on mobile or desktop browser 【发布时间】:2017-01-19 00:15:22 【问题描述】:

在 ReactJS 中,有没有办法确定网站是在移动设备还是桌面设备上查看?因为,取决于我想渲染不同的设备的设备。

谢谢

【问题讨论】:

我对很多答案并不感冒,这仅取决于屏幕宽度。以横向模式为例,我仍然想区分手机版和桌面版,尤其是控制功能。一个干净的设置应该能够区分:移动/平板电脑/桌面纵向/横向触摸/无触摸键/nokeys 最少但不是最后一个基于像素的断点 【参考方案1】:

React 不这样做,React 只是 MVC 中的视图。确定逻辑(控制应该查看的内容)是 Controller 的角色。 React 没有实现控制器,但认为应该由应用程序的其余部分来完成,因此您应该添加一些其他代码来控制 React 组件的上下文,甚至为不同的设备使用不同的组件。

【讨论】:

那么,您将如何使用 React 构建响应式页面? 同一个非反应页面,使用媒体查询。 React 在您的浏览器中生成 html,您可以对其应用媒体查询。 “确定逻辑(控制应该查看的内容)是控制器的角色”。媒体查询是控制器? 不,媒体查询是 CSS 的一部分,因此也是样式的一部分。基于某种模型(信息资源)的控制逻辑创建的内容。 @Anubhav Gupta 建议 react-responsive 似乎充当控制层来调整内容 我认为@AnubhavGupta 给出了一个很好的答案。但是,您最初的回答给我的印象是,用 React 控制应该或不应该查看哪些组件是错误的【参考方案2】:

您要查找的内容称为react-responsive。你可以找到它here

这是来自他们的仓库的how to use 快速指南:

var MediaQuery = require('react-responsive');

var A = React.createClass(
  render: function()
    return (
      <div>
        <div>Device Test!</div>

        <MediaQuery minDeviceWidth=1224>
          <div>You are a desktop or laptop</div>
        </MediaQuery>
        <MediaQuery maxDeviceWidth=1224>
          <div>You are a tablet or mobile phone</div>
        </MediaQuery>

        <MediaQuery orientation='portrait'>
          <div>You are portrait</div>
        </MediaQuery>
        <MediaQuery orientation='landscape'>
          <div>You are landscape</div>
        </MediaQuery>

        <MediaQuery minResolution='2dppx'>
          <div>You are retina</div>
        </MediaQuery>
      </div>
    );
  
);

【讨论】:

【参考方案3】:

我在 React 中使用了这种方法,它在 2020 年效果很好。感谢@Anubahav Gupta

npm install react-responsive --save

然后创建组件:

import React,  Fragment, Component  from 'react';
import MediaQuery from 'react-responsive';

class MyMediaQuery extends Component 
    render() 
        return (
            <Fragment>
                <div>Device Test!</div>

                <MediaQuery minDeviceWidth=1224>
                    <div>You are a desktop or laptop</div>
                </MediaQuery>
                <MediaQuery maxDeviceWidth=1224>
                    <div>You are a tablet or mobile phone</div>
                </MediaQuery>

                <MediaQuery orientation='portrait'>
                    <div>You are portrait</div>
                </MediaQuery>
                <MediaQuery orientation='landscape'>
                    <div>You are landscape</div>
                </MediaQuery>

                <MediaQuery minResolution='2dppx'>
                    <div>You are retina</div>
                </MediaQuery>
            </Fragment>
        );
    


export default MyMediaQuery;

它可以在任何加载的页面上按原样工作,但也可以通过以下方式导入另一个文件:

import MyMediaQuery from '.newFileName';

然后在任何地方用作:

<MyMediaQuery />

【讨论】:

【参考方案4】:

您可以使用React Device Detect Package

安装

要安装,可以使用 npm 或 yarn:

# For NPM:
npm install react-device-detect --save

# For Yarn
yarn add react-device-detect

用法

例子:

import BrowserView, MobileView from 'react-device-detect';

const MyComponent = () => 
    return (
        <>
            <BrowserView>
                <h1>This is rendered only in browser</h1>
            </BrowserView>
            <MobileView>
                <h1>This is rendered only on mobile</h1>
            </MobileView>
        </>
    );
;

如果不需要视图,可以使用isMobile进行条件渲染

import isMobile from 'react-device-detect';

const MyComponent = () => 
    if(isMobile) 
        return (
            <div> This content is available only on mobile</div>
        )
    
    return (
        <div> content... </div>
    );
;

取自React Device Detect README,稍作修改

【讨论】:

React 设备检测包工作得非常好,唯一的问题是它不会检测到用户何时调整页面大小。【参考方案5】:

既然可以使用一行普通的 javascript 代码,为什么还要让事情复杂化?

使用window.screen 对象获取当前屏幕的宽度。例如window.screen.width 将返回客户端当前宽度的值,以像素为单位。

if (window.screen.width &gt;= 1280) /* conditional statements */ 内部使用它

我希望它会有所帮助。谢谢你:-)

【讨论】:

我认为,如果您要在各个地方检查它是否是移动大小,则可以将其抽象为一个钩子,这样您就没有冗余你的代码。如果您确定支票是一次性的,那么这种方法似乎是合理的。【参考方案6】:

使用反应钩子的简单解决方案

const [width, setWidth] = useState<number>(window.innerWidth);

function handleWindowSizeChange() 
    setWidth(window.innerWidth);

useEffect(() => 
    window.addEventListener('resize', handleWindowSizeChange);
    return () => 
        window.removeEventListener('resize', handleWindowSizeChange);
    
, []);

const isMobile = width <= 768;

【讨论】:

简单不依赖包,这个应该更高 由于使用的是 window/useEffect 组合,这是否等待页面加载?在那种情况下,我认为它会导致可见的布局转变。下面列出的库有什么不同吗?我在 React 中检测窗口大小时遇到​​布局偏移问题【参考方案7】:

我进一步增强了 Volobot 的答案。我创建了一个如下的钩子,它的作用就像魅力:)

import React, useEffect, useState from "react";

const useCheckMobileScreen = () => 
    const [width, setWidth] = useState(window.innerWidth);
    const handleWindowSizeChange = () => 
            setWidth(window.innerWidth);
    

    useEffect(() => 
        window.addEventListener('resize', handleWindowSizeChange);
        return () => 
            window.removeEventListener('resize', handleWindowSizeChange);
        
    , []);

    return (width <= 768);


export default useCheckMobileScreen

【讨论】:

【参考方案8】:

这不是 React 特有的,但这是我的 js 函数:

export const isMobile = () => window.matchMedia && window.matchMedia("(max-width: 480px)").matches

【讨论】:

【参考方案9】:
const getNumberDesignRequest = screenWidth => 
  let numberDesignRequest = 20
  if (screenWidth >= 1280 && screenWidth < 1525) 
    numberDesignRequest = 21
  
  
  return numberDesignRequest


const ScreenWidth = () => 
  const [screenWidth, setScreenWidth] = useState(window.innerWidth)

  useLayoutEffect(() => 
    const handleResize = () => 
      const  innerWidth  = window
      setScreenWidth(innerWidth)
    

    window.addEventListener('resize', debounce(handleResize, 1000))
    return () => window.removeEventListener('resize', handleResize)
  , [])

  return screenWidth


const FuzzySearch = () => 
  const screenWidth = ScreenWidth()
const numberDesignRequest = getNumberDesignRequest(screenWidth)

【讨论】:

【参考方案10】:

创建一个自定义 Hook 并监听 Resize、load、orientationchange 和 reload 将重新渲染您使用此钩子的组件。

  import  useState, useEffect  from 'react';

  const useDeviceDetect = () => 
    const checkForDevice = () => 
      let windowWidth = window.innerWidth;
      if (windowWidth < 767.98) 
        return true;
       else 
        return false;
      
    ;

    const [isMobile, setIsMobile] = useState(checkForDevice());

    useEffect(() => 
      const handlePageResized = () => 
        setIsMobile(checkForDevice);
      ;

      window.addEventListener('resize', handlePageResized);
      window.addEventListener('orientationchange', handlePageResized);
      window.addEventListener('load', handlePageResized);
      window.addEventListener('reload', handlePageResized);

      return () => 
        window.removeEventListener('resize', handlePageResized);
        window.removeEventListener('orientationchange', handlePageResized);
        window.removeEventListener('load', handlePageResized);
        window.removeEventListener('reload', handlePageResized);
      ;
    , []);

    return 
      isMobile,
    ;
  ;

  export default useDeviceDetect;

【讨论】:

以上是关于ReactJS:如何确定应用程序是在移动浏览器还是桌面浏览器上查看的主要内容,如果未能解决你的问题,请参考以下文章

如何确定 iOS 设备是停止还是移动(驾驶)

如何识别网页是在 iframe 中加载还是直接加载到浏览器窗口中?

如何识别网页是在 iframe 中加载还是直接加载到浏览器窗口中?

Cordova/jQuery - 识别您的应用程序是在 Web/移动浏览器还是移动应用程序 (Android/iOS) 上运行

在同构 reactjs 中检测移动设备

ReactJS网站在移动浏览器上重新渲染和闪烁[关闭]