在ReactJS中获取视口/窗口高度

Jab*_*eed 122 javascript reactjs

如何获得视口的高度???

window.innerHeight()
Run Code Online (Sandbox Code Playgroud)

但是使用reactjs,我不知道如何获取这些信息.我的理解是

ReactDOM.findDomNode()
Run Code Online (Sandbox Code Playgroud)

仅适用于创建的组件.然而,文件身体元素不是这种情况,它可以给我窗户的高度.

spe*_*arp 211

这个答案类似于Jabran Saeed,除了它还处理窗口大小调整.我是从这里得到的.

constructor(props) {
  super(props);
  this.state = { width: 0, height: 0 };
  this.updateWindowDimensions = this.updateWindowDimensions.bind(this);
}

componentDidMount() {
  this.updateWindowDimensions();
  window.addEventListener('resize', this.updateWindowDimensions);
}

componentWillUnmount() {
  window.removeEventListener('resize', this.updateWindowDimensions);
}

updateWindowDimensions() {
  this.setState({ width: window.innerWidth, height: window.innerHeight });
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么不`this.state = {width:window.innerWidth,height:window.innerHeight};`开始? (7认同)
  • 你可以从回调参数中删除`.bind(this)`,因为它已经被构造函数绑定了. (3认同)

QoP*_*QoP 80

在React中它是相同的,您可以使用它16.8.0+来获取当前视口的高度.

正如你在这里看到的那样

  • 写得这么好的答案。希望更多的人写这样的 stackoverflow 答案,而不是发布 npm 模块。 (7认同)
  • 有什么想法可以通过 SSR (NextJS) 获得相同的方法吗? (3认同)
  • window.innerHeight不是函数,而是属性 (2认同)
  • 似乎Kevin Danikowski编辑了答案,并以某种方式批准了该更改。现在已修复。 (2认同)
  • @FeCH会在卸载组件时删除事件侦听器。它被称为“清理”功能,您可以在[此处](https://reactjs.org/docs/hooks-effect.html#example-using-hooks-1)进行阅读。 (2认同)

gio*_*pds 53

我刚刚编辑了QoP当前答案以支持SSR并将其与Next.js (React 16.8.0+) 一起使用:

/hooks/useWindowDimensions.js

import { useState, useEffect } from 'react';

export default function useWindowDimensions() {

  const hasWindow = typeof window !== 'undefined';

  function getWindowDimensions() {
    const width = hasWindow ? window.innerWidth : null;
    const height = hasWindow ? window.innerHeight : null;
    return {
      width,
      height,
    };
  }

  const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());

  useEffect(() => {
    if (hasWindow) {
      function handleResize() {
        setWindowDimensions(getWindowDimensions());
      }

      window.addEventListener('resize', handleResize);
      return () => window.removeEventListener('resize', handleResize);
    }
  }, [hasWindow]);

  return windowDimensions;
}
Run Code Online (Sandbox Code Playgroud)

/你的组件.js

import useWindowDimensions from './hooks/useWindowDimensions';

const Component = () => {
  const { height, width } = useWindowDimensions();
  /* you can also use default values or alias to use only one prop: */
  // const { height: windowHeight = 480 } useWindowDimensions();

  return (
    <div>
      width: {width} ~ height: {height}
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

  • 嗨乔瓦尼,感谢您的回答。是的,我明白你的代码在做什么。我的观点是向其他人表明,使用最新版本的 Next 它将触发警告(我同意你的观点,它仍然有效,这只是一个警告)。我在文档中找不到任何方法: 1. 在“下一步”中轻松忽略此警告。2. 调整代码,使其不会触发它。对于后者,如果您有任何指示,请告诉我;-) (2认同)

Jab*_*eed 50

class AppComponent extends React.Component {

  constructor(props) {
    super(props);
    this.state = {height: props.height};
  }

  componentWillMount(){
    this.setState({height: window.innerHeight + 'px'});
  }

  render() {
    // render your component...
  }
}
Run Code Online (Sandbox Code Playgroud)

设置道具

AppComponent.propTypes = {
 height:React.PropTypes.string
};

AppComponent.defaultProps = {
 height:'500px'
};
Run Code Online (Sandbox Code Playgroud)

视口高度现在在渲染模板中以{this.state.height}形式提供

  • 如果调整浏览器窗口大小,则此解决方案不会更新 (12认同)

Jas*_*llo 22

我使用 React Hooks 和调整大小功能找到了 QoP 和 spekledcarp 的答案的简单组合,代码行数略少:

const [width, setWidth]   = useState(window.innerWidth);
const [height, setHeight] = useState(window.innerHeight);
const updateDimensions = () => {
    setWidth(window.innerWidth);
    setHeight(window.innerHeight);
}
useEffect(() => {
    window.addEventListener("resize", updateDimensions);
    return () => window.removeEventListener("resize", updateDimensions);
}, []);
Run Code Online (Sandbox Code Playgroud)

哦,是的,请确保resize事件是双引号,而不是单引号。那个让我有点;)

  • 单引号有什么问题? (2认同)

foa*_*ahi 19

使用钩子:

使用useLayoutEffect在这里更有效

import { useState, useLayoutEffect } from 'react';

function getWindowDimensions() {
  const { innerWidth: width, innerHeight: height } = window;
  return {
    width,
    height
  };
}

export default function useWindowDimensions() {
  const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());

  useLayoutEffect(() => {
    function handleResize() {
      setWindowDimensions(getWindowDimensions());
    }

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return windowDimensions;
}
Run Code Online (Sandbox Code Playgroud)

用法:

const { height, width } = useWindowDimensions();
Run Code Online (Sandbox Code Playgroud)


小智 18

添加这个是为了多样性和简洁的方法。

该代码使用函数式风格方法。正如其他答案中提到的,我使用了 onresize 而不是 addEventListener 。

import { useState, useEffect } from "react";

export default function App() {
  const [size, setSize] = useState({
    x: window.innerWidth,
    y: window.innerHeight
  });
  const updateSize = () =>
    setSize({
      x: window.innerWidth,
      y: window.innerHeight
    });
  useEffect(() => (window.onresize = updateSize), []);
  return (
    <>
      <p>width is : {size.x}</p>
      <p>height is : {size.y}</p>
    </>
  );
}
Run Code Online (Sandbox Code Playgroud)


Jam*_* L. 12

@speckledcarp的答案很好,但是如果您需要在多个组件中使用此逻辑,可能会很乏味。您可以将其重构为HOC(高阶组件),以使此逻辑更易于重用。

withWindowDimensions.jsx

import React, { Component } from "react";

export default function withWindowDimensions(WrappedComponent) {
    return class extends Component {
        state = { width: 0, height: 0 };

        componentDidMount() {
            this.updateWindowDimensions();
            window.addEventListener("resize", this.updateWindowDimensions);
        }

        componentWillUnmount() {
            window.removeEventListener("resize", this.updateWindowDimensions);
        }

        updateWindowDimensions = () => {
            this.setState({ width: window.innerWidth, height: window.innerHeight });
        };

        render() {
            return (
                <WrappedComponent
                    {...this.props}
                    windowWidth={this.state.width}
                    windowHeight={this.state.height}
                    isMobileSized={this.state.width < 700}
                />
            );
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

然后在您的主要组件中:

import withWindowDimensions from './withWindowDimensions.jsx';

class MyComponent extends Component {
  render(){
    if(this.props.isMobileSized) return <p>It's short</p>;
    else return <p>It's not short</p>;
}

export default withWindowDimensions(MyComponent);
Run Code Online (Sandbox Code Playgroud)

如果还需要使用其他HOC,也可以“堆叠” HOC,例如 withRouter(withWindowDimensions(MyComponent))

编辑:我现在将使用React钩子(在上面的示例中),因为它们解决了HOC和类的一些高级问题


Alj*_*aro 9

再会,

我知道我参加这个聚会迟到了,但让我告诉你我的答案。

const [windowSize, setWindowSize] = useState(null)

useEffect(() => {
    const handleResize = () => {
        setWindowSize(window.innerWidth)
    }

    window.addEventListener('resize', handleResize)

    return () => window.removeEventListener('resize', handleResize)
}, [])
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请访问https://usehooks.com/useWindowSize/

  • 您是否应该在效果中调用handleResize() 来设置原始浏览器窗口大小?window.innerHeight也会得到高度 (3认同)

Mat*_*den 8

with a little typescript

import { useState, useEffect } from 'react';

interface WindowDimentions {
    width: number;
    height: number;
}

function getWindowDimensions(): WindowDimentions {
    const { innerWidth: width, innerHeight: height } = window;

    return {
      width,
      height
    };
  }
  
  export default function useWindowDimensions(): WindowDimentions {
    const [windowDimensions, setWindowDimensions] = useState<WindowDimentions>(
      getWindowDimensions()
    );
  
    useEffect(() => {
      function handleResize(): void {
        setWindowDimensions(getWindowDimensions());
      }
  
      window.addEventListener('resize', handleResize);

      return (): void => window.removeEventListener('resize', handleResize);
    }, []);
  
    return windowDimensions;
  }
Run Code Online (Sandbox Code Playgroud)


小智 7

我只是花了一些认真的时间来弄清React和滚动事件/位置的某些内容-因此对于那些仍在寻找的人,这是我发现的内容:

可以使用window.innerHeight或document.documentElement.clientHeight找到视口高度。(当前视口高度)

可以使用window.document.body.offsetHeight找到整个文档(正文)的高度。

如果您要查找文档的高度并知道何时到达最低点,这是我想出的:

if (window.pageYOffset >= this.myRefII.current.clientHeight && Math.round((document.documentElement.scrollTop + window.innerHeight)) < document.documentElement.scrollHeight - 72) {
        this.setState({
            trueOrNot: true
        });
      } else {
        this.setState({
            trueOrNot: false
        });
      }
    }
Run Code Online (Sandbox Code Playgroud)

(我的导航栏在固定位置为72px,因此使用-72可获得更好的滚动事件触发器)

最后,这是console.log()的许多滚动命令,可以帮助我主动计算数学。

console.log('window inner height: ', window.innerHeight);

console.log('document Element client hieght: ', document.documentElement.clientHeight);

console.log('document Element scroll hieght: ', document.documentElement.scrollHeight);

console.log('document Element offset height: ', document.documentElement.offsetHeight);

console.log('document element scrolltop: ', document.documentElement.scrollTop);

console.log('window page Y Offset: ', window.pageYOffset);

console.log('window document body offsetheight: ', window.document.body.offsetHeight);
Run Code Online (Sandbox Code Playgroud)

ew!希望它能对某人有所帮助!


Jas*_*Jin 5

您可以像这样创建自定义挂钩:useWindowSize()

import { useEffect, useState } from "react";
import { debounce } from "lodash";

const getWindowDimensions = () => {
  const { innerWidth: width, innerHeight: height } = window;
  return { width, height };
};

export function useWindowSize(delay = 0) {
  const [windowDimensions, setWindowDimensions] = useState(
    getWindowDimensions()
  );

  useEffect(() => {
    function handleResize() {
      setWindowDimensions(getWindowDimensions());
    }
    const debouncedHandleResize = debounce(handleResize, delay);
    window.addEventListener("resize", debouncedHandleResize);
    return () => window.removeEventListener("resize", debouncedHandleResize);
  }, [delay]);

  return windowDimensions;
}
Run Code Online (Sandbox Code Playgroud)