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

时间:2016-04-26 10:31:18

标签: javascript reactjs

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

window.innerHeight()

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

ReactDOM.findDomNode()

仅适用于创建的组件。但是文档 body 元素不是这种情况,它可以给我窗口的高度。

14 个答案:

答案 0 :(得分:178)

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

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 });
}

答案 1 :(得分:43)

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...
  }
}
  

设置道具

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

AppComponent.defaultProps = {
 height:'500px'
};
  

视口高度现在在渲染模板中以{this.state.height}显示

答案 2 :(得分:19)

使用挂钩(反应16.8.0+

创建useWindowDimensions挂钩。

import { useState, useEffect } from 'react';

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

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

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

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

  return windowDimensions;
}

之后你就可以在你的组件中使用它了

const Component = () => {
  const { height, width } = useWindowDimensions();

  return (
    <div>
      width: {width} ~ height: {height}
    </div>
  );
}

Working example

原始回答

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

正如您所见here

答案 3 :(得分:7)

我使用React Hooks和调整大小功能找到了一个简单的QoP和Speckledcarp答案的组合,只需更少的代码行:

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);
}, []);

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

答案 4 :(得分:6)

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

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}
                />
            );
        }
    };
}

然后在您的主要组件中:

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);

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

答案 5 :(得分:5)

我只是花了一些认真的时间来弄清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
        });
      }
    }

(我的导航栏在固定位置为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);

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

答案 6 :(得分:3)

我刚刚编辑了QoPcurrent answer以支持 SSR ,并将其与 Next.js 一起使用(反应16.8。 0 +):

/hooks/useWindowDimensions.js

    <record id="url_website" model="ir.config_parameter">
        <field name="key">url_website</field>
        <field name="value">http://google.com.pe</field>
    </record>

    <record model="ir.actions.server" id="action_open_url">
        <field name="name">action_open_url</field>
        <field name="type">ir.actions.server</field>
        <field name="model_id" ref="base.model_res_partner"/>
        <field name="code">
url = env['ir.config_parameter'].sudo().get_param('url_website')
action = {"type": "ir.actions.act_url",
          "url": url,
          "target": "new",}
        </field>
    </record>

    <menuitem id="menu_open_url"
        name="OPEN MY URL"
        action="action_open_url"
    />

/yourComponent.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;
}

答案 7 :(得分:3)

// just use (useEffect). every change will be logged with current value
import React, { useEffect } from "react";

export function () {
  useEffect(() => {
    window.addEventListener('resize', () => {
      const myWidth  = window.innerWidth;
      console.log('my width :::', myWidth)
   })
  },[window])

  return (
    <>
      enter code here
   </>
  )
}

答案 8 :(得分:3)

有一点打字稿

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;
  }

答案 9 :(得分:3)

为了多样性和干净的方法添加这个。

这段代码使用了函数式风格的方法。我使用了 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>
    </>
  );
}

答案 10 :(得分:1)

@speckledcarp和@Jamesl的回答都很出色。但是,就我而言,我需要一个组件,该组件的高度可以扩展整个窗口的高度,在渲染时有条件...。但是在render()中调用HOC会重新呈现整个子树。 BAAAD。

此外,我对获取值作为道具并不感兴趣,只是想要一个可以占据整个屏幕高度(或宽度,或两者兼有)的父级div

所以我写了一个提供整个高度(和/或宽度)div的Parent组件。景气。

一个用例:

class MyPage extends React.Component {
  render() {
    const { data, ...rest } = this.props

    return data ? (
      // My app uses templates which misbehave badly if you manually mess around with the container height, so leave the height alone here.
      <div>Yay! render a page with some data. </div>
    ) : (
      <FullArea vertical>
        // You're now in a full height div, so containers will vertically justify properly
        <GridContainer justify="center" alignItems="center" style={{ height: "inherit" }}>
          <GridItem xs={12} sm={6}>
            Page loading!
          </GridItem>
        </GridContainer>
      </FullArea>
    )

以下是组件:

import React, { Component } from 'react'
import PropTypes from 'prop-types'

class FullArea extends Component {
  constructor(props) {
    super(props)
    this.state = {
      width: 0,
      height: 0,
    }
    this.getStyles = this.getStyles.bind(this)
    this.updateWindowDimensions = this.updateWindowDimensions.bind(this)
  }

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

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

  getStyles(vertical, horizontal) {
    const styles = {}
    if (vertical) {
      styles.height = `${this.state.height}px`
    }
    if (horizontal) {
      styles.width = `${this.state.width}px`
    }
    return styles
  }

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

  render() {
    const { vertical, horizontal } = this.props
    return (
      <div style={this.getStyles(vertical, horizontal)} >
        {this.props.children}
      </div>
    )
  }
}

FullArea.defaultProps = {
  horizontal: false,
  vertical: false,
}

FullArea.propTypes = {
  horizontal: PropTypes.bool,
  vertical: PropTypes.bool,
}

export default FullArea

答案 11 :(得分:0)

你也可以试试这个:

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

componentWillMount(){
          console.log("WINDOW : ",window);
          this.setState({height: window.innerHeight + 'px',width:window.innerWidth+'px'});
      }

render() {
        console.log("VIEW : ",this.state);
}

答案 12 :(得分:0)

美好的一天,

我知道我这次聚会迟到了,但是让我告诉你我的答案。

const [windowSize, setWindowSize] = useState(null)

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

    window.addEventListener('resize', handleResize)

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

有关将来的详细信息,请访问https://usehooks.com/useWindowSize/

答案 13 :(得分:0)

即使在调整窗口大小后也能保持当前尺寸的简单方法:

//set up defaults on page mount
componentDidMount() {
  this.state = { width: 0, height: 0 };
  this.getDimensions(); 

  //add dimensions listener for window resizing
  window.addEventListener('resize', this.getDimensions); 
}

//remove listener on page exit
componentWillUnmount() {
  window.removeEventListener('resize', this.getDimensions); 
}

//actually set the state to the window dimensions
getDimensions = () => {
  this.setState({ width: window.innerWidth, height: window.innerHeight });
  console.log(this.state);
}