使用react js和orientationchange事件时如何检测移动网站的屏幕方向?

hit*_*ker 9 javascript dom-events reactjs

我想使用所有主要移动浏览器都支持的事件来检测屏幕方向orientationchange变化

我添加事件侦听器componentDidMount并从事件回调内部设置状态。

但是,我发现当事件由于从纵向更改为横向而首次触发时,状态不会更新为横向。然后,当我将方向从横向更改回纵向时,状态显示方向是横向。此后,每次我更改方向时,状态总是与实际方向相反。我不确定我是否应该使用某种生命周期反应方法,或者我的检测效果不好。

我使用 Chrome 开发者工具测试了代码Toggle device toolbar。这是我的代码:

import React from 'react';

class AppInfo extends React.Component {
  state = {
    screenOrientation: 'portrait'
  }

  isPortraitMode = () => {
    console.log(this.state);
    const { screenOrientation } = this.state;
    return screenOrientation === 'portrait';
  }

  setScreenOrientation = () => {
    if (window.matchMedia("(orientation: portrait)").matches) {
      console.log('orientation: portrait');
      this.setState({
        screenOrientation: 'portrait'
      });
    }

    if (window.matchMedia("(orientation: landscape)").matches) {
      console.log('orientation: landscape');
      this.setState({
        screenOrientation: 'landscape'
      });
    }
  }

  componentDidMount() {
    window.addEventListener('orientationchange', this.setScreenOrientation);
  }

  render() {
    console.log(`orientation: from render: isPortraitMode = ${this.isPortraitMode()}`);
    <div>
      Hello
    </div>
  }
}

export default AppInfo;
Run Code Online (Sandbox Code Playgroud)

Jul*_*lli 5

下面是一个使用 hooks for React 的实现,它使用来自GitHub的自定义钩子来跟踪屏幕方向,以获取和跟踪方向。每次使用 useEffect 挂载组件时,它都会创建事件侦听器,并且每次卸载组件时都会关闭侦听器:

import {useState, useEffect} from 'react'

const getOrientation = () =>
  window.screen.orientation.type

const useScreenOrientation = () => {
  const [orientation, setOrientation] =
    useState(getOrientation())

  const updateOrientation = event => {
    setOrientation(getOrientation())
  }

  useEffect(() => {
    window.addEventListener(
      'orientationchange',
      updateOrientation
    )
    return () => {
      window.removeEventListener(
        'orientationchange',
        updateOrientation
      )
    }
  }, [])

  return orientation
}

export default useScreenOrientation
Run Code Online (Sandbox Code Playgroud)

在我的 Android 手机中,方向的两个值是:“portrait-primary”和“landscape-secondary”。在我的 Ubuntu 系统中它是:“landscape-primary”。在我的 Windows 10 Surface Book 2 笔记本电脑模式中:“protrait-primary”。不能很好地处理向平板电脑的切换。而且它根本没有检测到方向的变化。所有这些都在 Chrome v 99.0.4844.84(官方版本)(64 位)下进行。Mac OS Monterey v 12.2.1 报告“landscape-primary”与 Chrome 版本相同。


Vah*_* Al 0

你的程序运行得很好,你只需要像这样记录它:

this.setState({screenOrientation: 'landscape'}, console.log('orientation: landscape'))
Run Code Online (Sandbox Code Playgroud)

其背后的原因是对 setState 的调用不是同步的,但 setState(updater,callback) 是一个异步函数,它将回调作为第二个参数。