这个React文档 的例子应该会有所帮助。
ref 和myOwnRef 都应该是DOM元素(或能够接受ref的组件)的ref 属性的值。
当像这样使用时,使用ExampleInput 的父函数组件将通过调用React.useRef()来创建自己的Reactref 。
下面的示例代码的实时演示 演示了一个示例。在此示例中,ParentComponent 使用自己的ref (parentRef )直接作用于YourComponent 中的元素。在YourComponent 中,myOwnRef 被用来直接作用于 DOM元素。
index.html
<!DOCTYPE html >
<html >
<head >
<title > React.forwardRef test</title >
<meta charset ="utf-8" >
<meta name ="viewport" content ="width=device-width, initial-scale=1,user-scalable=1" >
<link rel ="icon" href ="data:;" >
<link rel ="stylesheet" href ="./css/index.css" >
</head >
<body >
<div id ="testContainer" class ="testContainer" > </div >
<script src ="./index.js" > </script >
<noscript > Please enable javascript to view the site </noscript >
</body >
</html >
index.jsx
import React from 'react' ;
import ReactDOM from 'react-dom' ;
import './test.css' ;
const container = document .getElementById ( 'testContainer' );
const YourComponent = ( { value, onChange }, ref ) => {
const myOwnRef = React .useRef ( null );
const divRef = React .useRef ( null );
const doSomething = ( ) => {
myOwnRef.current .value = '' ;
}
const doSomethingElse = ( ) => {
if ( 'blink' == myOwnRef.current .value ) {
divRef.current .classList .add ( 'displayAnimatedBorder' );
}
}
return (
<div ref ={ divRef }>
<label
ref ={ ref }
style ={ { marginRight: '8px ' } }
>
Field Label
</label >
<input
ref ={ myOwnRef }
placeholder ={ value }
onChange ={ onChange }
onKeyUp ={ doSomethingElse }
onMouseDown ={ doSomething }
/>
</div >
);
}
const ExampleInput = React .forwardRef ( YourComponent );
function ParentComponent ( props ) {
const parentRef = React .useRef ();
const handleChange = ( ) => {
parentRef.current .classList .add ( 'ColorChangeToIndicateFieldWasEdited' );
}
return (
<div >
<ExampleInput
ref ={ parentRef }
value ={ props.someValue }
onChange ={ handleChange }
/>
</div >
);
}
ReactDOM .render (
<ParentComponent someValue ={ 'Placeholder ' } /> ,
container
);
test.css
.ColorChangeToIndicateFieldWasEdited {
background-color : yellow;
}
@keyframes blinky {
0% {
border : 8px solid rgba (255 , 0 , 0 , 0 );
}
100% {
border : 8px solid rgba (255 , 0 , 0 , 1 );
}
}
.displayAnimatedBorder {
padding : 8px ;
width : fit-content;
animation : 700ms ease 100ms 6 alternate none running blinky
}
更新
我已经更新了我的答案和实时演示 ,使用div
的另一个示例。在input
字段中输入文本“blink”会触发doSomethingElse 回调函数,以闪烁边框更新div
。
针对这个问题:
如果我有一个“div”组件。我需要使用ref到这个组件。
更准确地说,是到同一个组件,而不是到这个div组件的包装器或任何子元素吗?
我认为使用单词ref 存在混淆。在下面的文本中,我尝试使用React文档 使用的格式约定:
ref 通常指的是从调用函数 React.useRef()
返回的 React 对象,或者传递给由 React.forwardRef()
消费的组件。
ref
指 JSX DOM 元素上的属性。
ref 指我示例代码中传递给 YourComponent
的变量,由 React.forwardRef
处理。
你的问题似乎是在问:“如何在 YourComponent
中定义的 div
上使用 ref ,而不将 ref 关联到 div
的任何父组件或子组件?” 如果是这样,那么这个问题显示了对 React.forwardRef
目的的误解。
React.forwardRef
用于使父组件直接访问位于由 React.forwardRef
消费的组件内部的特定 JSX DOM 元素(或组件)。使用 ref 来指示所需的 JSX DOM 元素(或组件)。
因此,在我的示例代码中,
React.forwardRef
为
ParentComponent
直接提供了对位于
YourComponent
内部的
label
的访问。
YourComponent
被
React.forwardRef
使用。通过使用
React.forwardRef
将
ref parentRef 下传到
YourComponent
中。
YourComponent
的定义将变量名从
parentRef 更改为
ref ,并将
ref 分配给
label
的
ref
属性。此赋值声明我们要使用
parentRef 访问
label
(而不是其他元素)。
React.forwardRef
不需要为直接访问 input
和 div
提供 refs 。这是因为所有这些都在同一作用域中:
使用 React.useRef
创建的 refs myOwnRef 和 divRef ;
所需的 JSX DOM 元素;以及
回调函数 doSomething 和 doSomethingElse ,它们使用了这些 refs 。
在 ParentComponent
中使用 React.forwardRef
是有意义的,因为 handleChange 需要直接访问 label
,而 handleChange 并不是在与 label
相同的作用域中定义的。
进一步解释...
参考
JSX DOM元素(例如我更新后的回答中的div
)可以在其ref
属性上使用ref (例如divRef
)。我们之所以想要将ref 传递给div
的ref
属性,是为了远程控制div
。所谓远程控制,意思是不使用定义在div
本身上的事件监听器,而是可以使用定义在另一个元素或组件上的事件监听器来控制div
。例如,div
的行为(闪烁边框)并未定义在div
标签上。它是在从input
标签上的onKeyUp 事件监听器调用的doSomethingElse 事件处理程序中定义的。
在这种情况下,我们不需要使用React.forwardRef
,因为ref (divRef )、div
和doSomethingElse 都在YourComponent
的范围内声明。
React.forwardRef
但是,如果我们想要通过在父组件中定义的回调函数来影响DOM元素的行为(或访问其属性),该怎么办呢?这就是我们会使用React.forwardRef的时候。如果ParentComponent想要使用ref来控制YourComponent内部的label,它不能直接渲染YourComponent来实现。如果ParentComponent试图在YourComponent上使用ref属性,那个ref属性将无法让我们访问到所需的元素(label)。例如,以下方法将不起作用:
function ParentComponent ( props ) {
const parentRef = React .useRef ();
const handleChange = ( ) => {
parentRef.current .classList .add ( 'ColorChangeToIndicateFieldWasEdited' );
}
return (
<div >
<YourComponent
ref ={ parentRef }
value ={ props.someValue }
onChange ={ handleChange }
/>
</div >
);
}
我们需要使用
React.forwardRef
来更新
YourComponent
(通过将其包装到
ExampleInput
中)以便
YourComponent
可以通过
ExampleInput
获取
ref 。然后将该
ref 传递给
YourComponent
,以确切地指定我们希望从
ParentComponent
的
handleChange 回调函数中控制哪个元素。
React文档页面
使用Refs操纵DOM 应该能提供帮助。