Ota*_*der 15 javascript reactjs
我正在创建一个组件,我需要获取它的父<div>宽度和高度。我正在使用 Hooks,所以我所有的组件都是函数。我已经阅读了一些使用类的示例,但这不适用于我的组件。
所以我有这个组件:
export default function PlantationMap(props) {
<div className="stage-canvas">
<Stage
width={window.innerWidth * 0.5}
height={window.innerHeight * 0.5}
onWheel={handleWheel}
scaleX={stage.stageScale}
scaleY={stage.stageScale}
x={stage.stageX}
y={stage.stageY}
draggable
/ >
</div>
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能获得<div>要使用的高度和宽度<Stage width={} height={} />?
非常感谢您提前
编辑:我尝试使用useRef()钩子,如下所示:
const div = useRef();
return (
<div ref={div}>
...
</div>
)
Run Code Online (Sandbox Code Playgroud)
但我无法访问该div.current对象
Bru*_*ith 15
我认为 useCallback 是您想要使用的,因此您可以在更改时获取宽度和高度。
const [height, setHeight] = useState(null);
const [width, setWidth] = useState(null);
const div = useCallback(node => {
if (node !== null) {
setHeight(node.getBoundingClientRect().height);
setWidth(node.getBoundingClientRect().width);
}
}, []);
return (
<div ref={div}>
...
</div>
)
Run Code Online (Sandbox Code Playgroud)
Dan*_*ins 14
您可以使用内置的ResizeObserver:
export default function PlantationMap(props) {
const [width, setWidth] = useState(100);
const [height, setHeight] = useState(100);
useEffect(() => {
const resizeObserver = new ResizeObserver((event) => {
// Depending on the layout, you may need to swap inlineSize with blockSize
// https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry/contentBoxSize
setWidth(event[0].contentBoxSize[0].inlineSize);
setHeight(event[0].contentBoxSize[0].blockSize);
});
resizeObserver.observe(document.getElementById("div1"));
});
return (
<div id="div1" className="stage-canvas">
<Stage
width={width * 0.5}
height={height * 0.5}
onWheel={handleWheel}
scaleX={stage.stageScale}
scaleY={stage.stageScale}
x={stage.stageX}
y={stage.stageY}
draggable
/ >
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
使用useRef钩子声明一个引用,然后读取current.offsetHeight和current.offsetWidth属性。
这是代码:
import React, { useEffect, useRef } from 'react';
const PlantationMap = (props) => {
const stageCanvasRef = useRef(null);
// useEffect will run on stageCanvasRef value assignment
useEffect( () => {
// The 'current' property contains info of the reference:
// align, title, ... , width, height, etc.
if(stageCanvasRef.current){
let height = stageCanvasRef.current.offsetHeight;
let width = stageCanvasRef.current.offsetWidth;
}
}, [stageCanvasRef]);
return(
<div className = "stage-canvas" ref = {stageCanvasRef}>
<Stage
width={window.innerWidth * 0.5}
height={window.innerHeight * 0.5}
onWheel={handleWheel}
scaleX={stage.stageScale}
scaleY={stage.stageScale}
x={stage.stageX}
y={stage.stageY}
draggable
/ >
</div>);
}
export default PlantationMap;
Run Code Online (Sandbox Code Playgroud)
我认为 ResizeObserver 是 Dan 的答案中提到的方法。我只是不会使用document.getElementById. 要么使用useMeasurereact -use,要么自己创建一切。
有两种情况:
至 1 - 可直接访问的参考
useRef在这种情况下,您可以在组件中创建引用并在 处使用它resizeObserver.observe(demoRef.current)。
import "./styles.css";
import React, { useEffect, useRef, useState } from "react";
const DisplaySize = ({ width, height }) => (
<div className="centered">
<h1>
{width.toFixed(0)}x{height.toFixed(0)}
</h1>
</div>
);
const Demo = () => {
const [width, setWidth] = useState(100);
const [height, setHeight] = useState(100);
const demoRef = useRef();
useEffect(() => {
const resizeObserver = new ResizeObserver((event) => {
// Depending on the layout, you may need to swap inlineSize with blockSize
// https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry/contentBoxSize
setWidth(event[0].contentBoxSize[0].inlineSize);
setHeight(event[0].contentBoxSize[0].blockSize);
});
if (demoRef) {
resizeObserver.observe(demoRef.current);
}
}, [demoRef]);
return (
<div ref={demoRef} className="App">
<DisplaySize width={width} height={height} />
</div>
);
}; //);
export default function App() {
return <Demo />;
}
Run Code Online (Sandbox Code Playgroud)
至 2 - 无法直接访问的容器的引用:
这种情况可能发生得更频繁,并且需要的代码稍微多一些。您需要使用 来将引用从父组件传递到子组件React.forwardRef。
代码中的一些话:
const containerRef = useRef()并在主容器中使用它<div ref={containerRef}/>。在引擎盖下它会做类似的事情ref => containerRef.current=refDemo组件。为什么不使用React.createRef?
这也可以,但它会在应用程序的每个渲染上重新创建引用。请查看此处,useRef了解和之间的区别的解释createRef。
简而言之,与功能组件一起使用并与基于类的组件一起useRef使用。createRef
const {useEffect, useRef, useState} = React;
const DisplaySize = ({ width, height }) => (
<div className="centered">
<h1>
{width.toFixed(0)}x{height.toFixed(0)}
</h1>
</div>
);
const Demo = React.forwardRef((props, ref) => {
const [width, setWidth] = useState(100);
const [height, setHeight] = useState(100);
useEffect(() => {
const resizeObserver = new ResizeObserver((event) => {
// Depending on the layout, you may need to swap inlineSize with blockSize
// https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry/contentBoxSize
setWidth(event[0].contentBoxSize[0].inlineSize);
setHeight(event[0].contentBoxSize[0].blockSize);
});
if (ref && ref.current) {
resizeObserver.observe(ref.current);
}
}, [ref]);
return <DisplaySize width={width} height={height} />;
});
function App() {
const containerRef = useRef();
return (
<div ref={containerRef} className="App">
<Demo ref={containerRef} />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<App />,
rootElement
);Run Code Online (Sandbox Code Playgroud)
/* apply a natural box layout model to all elements, but allowing components to change */
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
html,
body {
margin: 0;
padding: 0;
}
.App {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
font-family: sans-serif;
text-align: center;
border: 4px solid red;
}
.centered {
display: flex; /* establish flex container */
flex-direction: column; /* make main axis vertical */
justify-content: center; /* center items vertically, in this case */
align-items: center; /* center items horizontally, in this case */
height: 100%;
}Run Code Online (Sandbox Code Playgroud)
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>Run Code Online (Sandbox Code Playgroud)
还有一些有用的钩子React-use可以在这里提供帮助。
useWindowSize看起来useSize非常相似,但在查看源代码之后,第一个依赖于window.onresize事件并且需要更少的代码来实现。
useSize将在当前组件 ( z-index: -1) 下方添加一个 iframe 以通过事件跟踪大小resize,并且需要更多代码。它还增加了一点去抖功能setTimeout。
因此,useWindowSize如果您只需要宽度/高度在第一次渲染时进行一些计算,并且useSize您想显示大小已更改,请使用。
如果您只需要获取窗口大小,则可以使用WindowSize 。他们通过 onresize 事件来完成此操作并检查document.addEventlistener('resize', resizeHandler)CodesandboxinnerWidth / innerHeight
演示
要跟踪元素大小,useMeasure可以使用。它ResizeObserver在幕后使用,所以就像上面的代码一样,其中是ref您要跟踪的引用:
返回的第一个元素useMeasure是setRef方法。因此,您可以在组件中执行以下操作:
const [setRef, { width, height }] = useMeasure();
useEffect(() => {
setRef(ref.current)
}, [])
Run Code Online (Sandbox Code Playgroud)
请看看下面的Codesandbox。
如果您想跟踪组件的大小,useSize可以使用文档中提到的方法。
Codesandbox 演示useSize
据我所知,如果涉及风格只能通过以下方式注册:
<Stage style={{width:window.innerWidth * 0.5,height:width:window.innerWidth * 0.5}} />
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
32924 次 |
| 最近记录: |