1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > [OHIF-Viewers]医疗数字阅片-医学影像-REACT-React.createRef()-Refs and the DOM关于回调 refs 的说明...

[OHIF-Viewers]医疗数字阅片-医学影像-REACT-React.createRef()-Refs and the DOM关于回调 refs 的说明...

时间:2023-07-19 02:21:41

相关推荐

[OHIF-Viewers]医疗数字阅片-医学影像-REACT-React.createRef()-Refs and the DOM关于回调 refs 的说明...

[OHIF-Viewers]医疗数字阅片-医学影像-REACT-React.createRef()-Refs and the DOM关于回调 refs 的说明

const [downloadCanvas, setDownloadCanvas] = useState({ref: createRef(),width: defaultSize,height: defaultSize,});

Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素。

在典型的 React 数据流中,props是父组件与子组件交互的唯一方式。要修改一个子组件,你需要使用新的 props 来重新渲染它。但是,在某些情况下,你需要在典型数据流之外强制修改子组件。被修改的子组件可能是一个 React 组件的实例,也可能是一个 DOM 元素。对于这两种情况,React 都提供了解决办法。

何时使用 Refs

下面是几个适合使用 refs 的情况:

管理焦点,文本选择或媒体播放。触发强制动画。集成第三方 DOM 库。

避免使用 refs 来做任何可以通过声明式实现来完成的事情。

举个例子,避免在Dialog组件里暴露open()close()方法,最好传递isOpen属性。

勿过度使用 Refs

你可能首先会想到使用 refs 在你的 app 中“让事情发生”。如果是这种情况,请花一点时间,认真再考虑一下 state 属性应该被安排在哪个组件层中。通常你会想明白,让更高的组件层级拥有这个 state,是更恰当的。查看状态提升以获取更多有关示例。

注意

下面的例子已经更新为使用在 React 16.3 版本引入的React.createRef()API。如果你正在使用一个较早版本的 React,我们推荐你使用回调形式的 refs。

创建 Refs

Refs 是使用React.createRef()创建的,并通过ref属性附加到 React 元素。在构造组件时,通常将 Refs 分配给实例属性,以便可以在整个组件中引用它们。

class MyComponent extends ponent {constructor(props) {super(props);this.myRef = React.createRef(); }render() {return <div ref={this.myRef} />; }}

访问 Refs

当 ref 被传递给render中的元素时,对该节点的引用可以在 ref 的current属性中被访问。

const node = this.myRef.current;

ref 的值根据节点的类型而有所不同:

ref属性用于 HTML 元素时,构造函数中使用React.createRef()创建的ref接收底层 DOM 元素作为其current属性。当ref属性用于自定义 class 组件时,ref对象接收组件的挂载实例作为其current属性。你不能在函数组件上使用ref属性,因为他们没有实例。

以下例子说明了这些差异。

为 DOM 元素添加 ref

以下代码使用ref去存储 DOM 节点的引用:

class CustomTextInput extends ponent {constructor(props) {super(props);// 创建一个 ref 来存储 textInput 的 DOM 元素this.textInput = React.createRef(); this.focusTextInput = this.focusTextInput.bind(this);}focusTextInput() {// 直接使用原生 API 使 text 输入框获得焦点// 注意:我们通过 "current" 来访问 DOM 节点this.textInput.current.focus(); }render() {// 告诉 React 我们想把 <input> ref 关联到// 构造器里创建的 `textInput` 上return (<div><inputtype="text"ref={this.textInput} /> <inputtype="button"value="Focus the text input"onClick={this.focusTextInput}/></div>);}}

React 会在组件挂载时给current属性传入 DOM 元素,并在组件卸载时传入null值。ref会在componentDidMountcomponentDidUpdate生命周期钩子触发前更新。

为 class 组件添加 Ref

如果我们想包装上面的CustomTextInput,来模拟它挂载之后立即被点击的操作,我们可以使用 ref 来获取这个自定义的 input 组件并手动调用它的focusTextInput方法:

class AutoFocusTextInput extends ponent {constructor(props) {super(props);this.textInput = React.createRef(); }componentDidMount() {this.textInput.current.focusTextInput(); }render() {return (<CustomTextInput ref={this.textInput} /> );}}

请注意,这仅在CustomTextInput声明为 class 时才有效:

class CustomTextInput extends ponent { // ... }

Refs 与函数组件

默认情况下,你不能在函数组件上使用ref属性,因为它们没有实例:

function MyFunctionComponent() { return <input />;}class Parent extends ponent {constructor(props) {super(props);this.textInput = React.createRef(); }render() {// This will *not* work!return (<MyFunctionComponent ref={this.textInput} /> );}}

如果要在函数组件中使用ref,你可以使用forwardRef(可与useImperativeHandle结合使用),或者可以将该组件转化为 class 组件。

不管怎样,你可以在函数组件内部使用ref属性,只要它指向一个 DOM 元素或 class 组件:

function CustomTextInput(props) {// 这里必须声明 textInput,这样 ref 才可以引用它 const textInput = useRef(null);function handleClick() {textInput.current.focus(); }return (<div><inputtype="text"ref={textInput} /><inputtype="button"value="Focus the text input"onClick={handleClick}/></div>);}

将 DOM Refs 暴露给父组件

在极少数情况下,你可能希望在父组件中引用子节点的 DOM 节点。通常不建议这样做,因为它会打破组件的封装,但它偶尔可用于触发焦点或测量子 DOM 节点的大小或位置。

虽然你可以向子组件添加 ref,但这不是一个理想的解决方案,因为你只能获取组件实例而不是 DOM 节点。并且,它还在函数组件上无效。

如果你使用 16.3 或更高版本的 React, 这种情况下我们推荐使用ref 转发。Ref 转发使组件可以像暴露自己的 ref 一样暴露子组件的 ref。关于怎样对父组件暴露子组件的 DOM 节点,在ref 转发文档中有一个详细的例子。

如果你使用 16.2 或更低版本的 React,或者你需要比 ref 转发更高的灵活性,你可以使用这个替代方案将 ref 作为特殊名字的 prop 直接传递。

可能的话,我们不建议暴露 DOM 节点,但有时候它会成为救命稻草。注意这个方案需要你在子组件中增加一些代码。如果你对子组件的实现没有控制权的话,你剩下的选择是使用findDOMNode(),但在严格模式下已被废弃且不推荐使用。

回调 Refs

React 也支持另一种设置 refs 的方式,称为“回调 refs”。它能助你更精细地控制何时 refs 被设置和解除。

不同于传递createRef()创建的ref属性,你会传递一个函数。这个函数中接受 React 组件实例或 HTML DOM 元素作为参数,以使它们能在其他地方被存储和访问。

下面的例子描述了一个通用的范例:使用ref回调函数,在实例的属性中存储对 DOM 节点的引用。

class CustomTextInput extends ponent {constructor(props) {super(props);this.textInput = null;this.setTextInputRef = element => {this.textInput = element; };this.focusTextInput = () => {// 使用原生 DOM API 使 text 输入框获得焦点if (this.textInput) this.textInput.focus(); }; }componentDidMount() {// 组件挂载后,让文本框自动获得焦点this.focusTextInput(); }render() {// 使用 `ref` 的回调函数将 text 输入框 DOM 节点的引用存储到 React// 实例上(比如 this.textInput)return (<div><inputtype="text"ref={this.setTextInputRef} /><inputtype="button"value="Focus the text input"onClick={this.focusTextInput} /></div>);}}

React 将在组件挂载时,会调用ref回调函数并传入 DOM 元素,当卸载时调用它并传入null。在componentDidMountcomponentDidUpdate触发前,React 会保证 refs 一定是最新的。

你可以在组件间传递回调形式的 refs,就像你可以传递通过React.createRef()创建的对象 refs 一样。

function CustomTextInput(props) {return (<div><input ref={props.inputRef} /> </div>);}class Parent extends ponent {render() {return (<CustomTextInputinputRef={el => this.inputElement = el}/>);}}

在上面的例子中,Parent把它的 refs 回调函数当作inputRefprops 传递给了CustomTextInput,而且CustomTextInput把相同的函数作为特殊的ref属性传递给了<input>。结果是,在Parent中的this.inputElement会被设置为与CustomTextInput中的input元素相对应的 DOM 节点。

过时 API:String 类型的 Refs

如果你之前使用过 React,你可能了解过之前的 API 中的 string 类型的 ref 属性,例如"textInput"。你可以通过this.refs.textInput来访问 DOM 节点。我们不建议使用它,因为 string 类型的 refs 存在一些问题。它已过时并可能会在未来的版本被移除。

注意

如果你目前还在使用this.refs.textInput这种方式访问 refs ,我们建议用回调函数或createRefAPI的方式代替。

关于回调 refs 的说明

如果ref回调函数是以内联函数的方式定义的,在更新过程中它会被执行两次,第一次传入参数null,然后第二次会传入参数 DOM 元素。这是因为在每次渲染时会创建一个新的函数实例,所以 React 清空旧的 ref 并且设置新的。通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题,但是大多数情况下它是无关紧要的。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。