资讯专栏INFORMATION COLUMN

如何在 React 组件中正确使用 Refs的指南

Backache / 1484人阅读

摘要:通常在组件的构造函数内创建,使其在整个组件中可用。例如纯文本查看复制代码如上所示一个实例在构造函数中创建,并赋值给在方法内部,将构造函数中创建的传递给接下来,让我们看一个在组件中使用的示例。回调回调是在中使用的另一种方式。

使用 React 时,我们的默认思维方式应该是 不会强制修改 DOM ,而是通过传入 props 重新渲染组件。但是,有些情况却无法避免修改 DOM 。
React 中的 Refs 提供了一种访问 render() 方法中创建的 React 元素(或 DOM 节点)的方法。
当父组件需要与子组件交互时,我们通常使用 props 来传递相关信息。 但是,在某些情况下,我们可能需要修改子项,而不用新的props 重新呈现 (re-rendering) 它。 这时候就需要 refs 出场了。
我什么时候应该使用 Refs ?
我们建议在以下情况下使用 refs:
与第三方 DOM 库集成
触发命令式动画
管理焦点,文本选择或媒体播放

译注:第三点是否也可以理解为使用 event 对象呢?在 React 中就是合成事件(SyntheticEvent)。
官方文档中提到:避免使用 refs 来做任何可以通过声明式实现来完成的事情。
所以一旦我们确定我们真的应该使用 refs,我们需要如何使用它们呢?
在 React 中使用 Refs
您可以通过多种方式使用 refs :
React.createRef()
回调引用 (Callback refs)
String refs(已过时)
转发 refs (Forwarding refs)

接下来,让我们看看每一种实现方式:
React.createRef()
可以使用该 React.createRef() 函数创建 Refs ,并通过该 ref 属性附加到 React 组件中的 HTML 元素。
通常在组件的构造函数内创建 ref ,使其在整个组件中可用。例如:
[JavaScript] 纯文本查看 复制代码
?

class MyComponent extends React.Component {
constructor(props) {
super(props);
this.firstRef = React.createRef();
}
render() {
return

;
}}
如上所示:
一个 ref 实例在构造函数中创建,并赋值给 this.firstRef
在 render() 方法内部,将构造函数中创建的 ref 传递给 div

接下来,让我们看一个在 React 组件中使用 refs 的示例。
使用 Refs 聚焦输入
这是另一个例子:
[JavaScript] 纯文本查看 复制代码
?

// Ref.jsclass CustomTextInput extends React.Component {
constructor(props) {
super(props);
// create a ref to store the textInput DOM element
this.textInput = React.createRef();
this.focusTextInput = this.focusTextInput.bind(this);
}

focusTextInput() {
// Explicitly focus the text input using the raw DOM API
// Note: we"re accessing "current" to get the DOM node
this.textInput.current.focus();
}

render() {
// tell React that we want to associate the ref
// with the textInput that we created in the constructor
return (



);
}}
在上面的代码块中,我们构建了一个按钮,当单击它时,该页面会自动聚焦在输入框上。
首先,我们在构造方法中创建一个 ref 实例,并将其赋值给 this.textInput,然后通过 ref 属性将其分配给 input 元素。
[HTML] 纯文本查看 复制代码
?
1

注意,当 ref 属性被一个 HTML 元素使用时(比如当前示例中的 input 元素),在 constructor 中使用 React.createRef() 创建的 ref 会接收来自底层 DOM 元素的 current 值。
译注:这里的 current 应该是 合成事件(SyntheticEvent)
这意味着访问 DOM 值,我们需要写这样的东西:
[JavaScript] 纯文本查看 复制代码
?
1
this.textInput.current;

第二个元素是一个按钮,点击它之后会自动聚焦到第一个输入框上面。我们为 onClick 属性设置了 this.focusTextInput 函数。
[JavaScript] 纯文本查看 复制代码
?

type="button"
value="Focus the text input"
onClick={this.focusTextInput}/>
函数 focusTextInput() 使用了 JavaScript 构建 DOM 的标准函数。 .focus() 方法会将光标聚焦于文本输入框上。
[JavaScript] 纯文本查看 复制代码
?

focusTextInput() {
this.textInput.current.focus();}
最后,focusTextInput 函数绑定在这样的 constructor 方法中的:
[JavaScript] 纯文本查看 复制代码
?

this.focusTextInput = this.focusTextInput.bind(this);
从 ref 中获取值
在这个例子中,我们将看到如何为 input 输入框设置 ref 属性,并通过 ref 来获取值。示例如下:
在这个例子中,我们创建了一个 input 输入框来输入值。然后,当单击提交按钮时,我们将读取此值,并在控制台打印。
[JavaScript] 纯文本查看 复制代码
?

// Ref.jsclass CustomTextInput extends React.Component {
constructor(props) {
super(props);
// create a ref to store the textInput DOM element
this.textInput = React.createRef();
}
handleSubmit = e => {
e.preventDefault();

console.log(this.textInput.current.value);
};

render() {
// tell React that we want to associate the ref
// with the textInput that we created in the constructor
return (


this.handleSubmit(e)}>




);
}}
同样,我们使用该 React.createRef() 函数创建一个 ref 实例,然后将它分配给实例变量 this.textInput。
在 render 函数中,我们希望读取 form 下输入框的值。我们如何读取这个值? 通过为 input 指定一个 ref ,然后读取 ref 的值。
[JavaScript] 纯文本查看 复制代码
?
1

点击提交按钮,上面示例中 form 元素会通过 onSubmit 方法,调用 this.handleSubmit 函数 ,并在控制台打印输入框中的信息。
[JavaScript] 纯文本查看 复制代码
?

handleSubmit = e => {
e.preventDefault();
console.log(this.textInput);};
上面,参数 e 包含事件对象。我们使用e.preventDefault() 来告诉浏览器我们正在处理被点击的提交按钮,我们不希望这个事件“冒泡”(意思就是说,阻止浏览器的默认行为)。
译注:这里可以看一下 React 对于事件的处理:在 React 中另一个不同点是你不能通过返回 false 的方式阻止默认行为。你必须显式的使用 preventDefault
在上面示例中,我们打印了 this.textInput ,在控制台可以看到一个 ref 对象。
[JavaScript] 纯文本查看 复制代码
?
1

Object {current: HTMLInputElement}
请注意,它有一个 current属性,即 HTMLInputElement 。这是 input DOM 元素本身,而不是实际值。 我们必须使用 this.textInput.current.value 来获取 input 标签的实际值:
[JavaScript] 纯文本查看 复制代码
?

handleSubmit = e => {
e.preventDefault();
console.log(this.textInput.current.value);};
使用 refs 是一种从表单中直接提取值的方式:只需要给 input 标签设置 ref ,并在你需要的时候将值提取出来。
Refs 回调
Refs 回调 是在 React 中使用 ref 的另一种方式。要以这种方式使用 ref,我们需要为 ref 属性设置回调函数。当我们设置 ref 时,React 会调用这个函数,并将 element 作为第一个参数传递给它。
这是另一个例子的代码。像上面的示例一样,此代码获取 input 标签的文本值,但在这里我们使用回调引用:
[JavaScript] 纯文本查看 复制代码
?

// Refs.jsclass CustomTextInput extends React.Component {
constructor(props) {
super(props);
this.textInput = null;

this.setTextInputRef = element => {
this.textInput = element;
};
}

handleSubmit = e => {
e.preventDefault();
console.log(this.textInput.value);
};

render() {
return (


this.handleSubmit(e)}>




);
}}
上面的示例中,我们将 input 标签的 ref 设置为 this.setTextInputRef。
当组件安装时,React 会将 DOM 元素传递给 ref 的回调;当组件卸载时,则会传递 null。(ref 回调会在 componentDidMount 和 componentDidUpdate 生命周期之前调用。)
String Ref(已过时)
还有另一种设置 refs 的方法,但它被认为是过时的,可能很快就会被弃用。但是你可能会在其他人的代码中看到它,所以这里说一下。
使用 string refs,你将会看到这样的 input 标签:
[HTML] 纯文本查看 复制代码
?

然后,我们可以在组建上得到这样的值:this.refs.textInput.value - 但是,再次声明,这不应该在新代码中使用,因为这个 API 将被弃用。
转发 Refs (Forwarding Refs)
Ref forwarding 是一种将 ref 通过组件传递给其子节点的技术。它对于可复用组件库和高阶组件(HOC)等情况非常有用。
您可以使用 React.forwardRef 函数将 ref 转发到组件。我们来看下面的例子:
[JavaScript] 纯文本查看 复制代码
?

// Ref.jsconst TextInput = React.forwardRef((props, ref) => (
));const inputRef = React.createRef();class CustomTextInput extends React.Component {
handleSubmit = e => {
e.preventDefault();
console.log(inputRef.current.value);
};

render() {
return (


this.handleSubmit(e)}>




);
}}
Ref forwarding 允许组件接收一个 ref ,并将它向下传递(换句话说,“转发”它)给子组件。
在上面的示例中,我们使用 input 标签创建了一个名为 TextInput 的组件。那么,我们如何将 ref 传递或转发到 input 标签呢?
首先,我们使用下面的代码创建一个 ref :
[JavaScript] 纯文本查看 复制代码
?
1
const inputRef = React.createRef();

然后,我们将 ref 通过为组件 指定一个同名的 JSX 的属性,将 ref 向下传递。然后 React 将会把 ref 作为第二个参数转发给 forwardRef 函数。
接下来,我们将此 ref 参数转发给 。现在可以在外层组件通过 inputRef.current 访问DOM节点的值了。
转发 refs 和高阶组件
最后,让我们看一下使用 refs 的另一个例子,但这次是使用高阶组件(HOC)。
在上面的示例应用程序中,会将所有 input 标签中输入的值在控制台打印。这里已经为 input 标签设置了 ref 属性,接下来,让我们看一下需要如何在高阶组件中传递 / 转发 ref 。
[JavaScript] 纯文本查看 复制代码
?

const Input = InputComponent => {
const forwardRef = (props, ref) => {
const onType = () => console.log(ref.current.value);
return ;
};
return React.forwardRef(forwardRef);};
这里有一个名为 Input 的高阶组件 ,它接受 InputComponent 作为参数。当用户输入的时候,他还会将 ref 的值在控制台打印。
在 Input 高阶组件内,forwardRef 函数会返回 InputComponent。forwardRef 函数中所包含的 ref 参数,是由 React.forwardRef 函数创建的。 高阶组件最终会将包装好的组件作为值返回。
接下来,我们创建一个组件,将 input 作为子组件包含进来。
[JavaScript] 纯文本查看 复制代码
?

const TextInput = ({ forwardedRef, children, ...rest }) => (



{children}
);
上面的组件会将 forwardedRef 分配给 ref 属性, 当渲染子组件的时候,input 输入框就会接收到这个 ref 。…rest 是 props 的解构(也就是说,我们会将 rest 数组中的所有参数作为 props 传递给 input 组件)。那么我们该如何使用 TextInput 组件呢?像这样:
[JavaScript] 纯文本查看 复制代码
?

const InputField = Input(TextInput);class CustomTextInput extends Component {
render() {
const inputRef = React.createRef();

return ;
}}
最后,将 TextInput 传入 Input 高阶组件,会返回一个 InputField component。
创建一个 ref ,并作为参数传递给 InputField 组件。
结论
与通过 props 和 state 不同,Refs 是一种将数据传递给特定子实例的好方法。
你必须要小心,因为 refs 操纵实际的 DOM,而不是虚拟的 DOM,这与 React 思维方式相矛盾。因此,虽然 refs 不应该是通过应用程序流动数据的默认方法,但是当您需要时,它们是可以从 DOM 元素读取数据的好方法。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/53972.html

相关文章

  • 02.react进阶指南

    摘要:指定读取当前的。它为其后代元素触发额外的检查和警告。严格模式检查仅在开发模式下运行它们不会影响生产构建。作用识别不安全的生命周期关于使用过时字符串的警告关于使用废弃的方法的警告检测意外的副作用检测过时的为高阶组件。 react 进阶 懒加载 React.lazy函数能让你像渲染常规组件一样处理动态引入(的组件)。Suspense加载指示器为组件做优雅降级。fallback属性接受任何在...

    zzbo 评论0 收藏0
  • ReactRefs方法获取DOM实例 和 访问子组件方法及属性

    摘要:绑定属性调用的时候使用调用子组件方法这是一个很神奇的方法,它可以调用子组件的方法以及属性。建立组件建立子组件,并在子组件实现一个方法,如,这个方法实现变更当前组件上面的文本,提供这样一个测试用例。输入框获取焦点完整实例点我输入框获取焦点 React 支持一种非常特殊的属性 Ref ,你可以用来绑定到 render() 输出的任何组件上。 ref : 绑定属性 refs : 调用的时候...

    geekzhou 评论0 收藏0
  • React教程:组件,Hooks和性能

    摘要:顾名思义,受控组件的值由控制,能为与用户交互的元素提供值,而不受控制的元素不获取值属性。另外我发现受控组件更容易理解和于使用。只是一种把组件作为参数的函数,并且与没有包装器的组件相比,能够返回具有扩展功能的新组件。其中三个基本的是,和。 翻译:疯狂的技术宅原文:https://www.toptal.com/react/... 本文首发微信公众号:jingchengyideng欢迎关...

    edagarli 评论0 收藏0
  • React

    摘要:基础创建虚拟参数元素名称,例如参数属性集合,例如,,,从参数开始,表示该元素的子元素,通常这些元素通过创建,文本文件可以直接插入嘻嘻哈哈这是渲染器,将元素渲染到页面中。 React简介 FeceBook开源的一套框架,专注于MVC的视图V模块。实质是对V视图的一种实现。 React框架的设计没有过分依赖于某个环境,它自建一套环境,就是virtual DOM(虚拟DOM)。 提供基础AP...

    hlcc 评论0 收藏0
  • React系列---React(二)组件prop和state

    摘要:给赋值也是构造函数的工作之一。在的构造函数中,还给两个成员函数绑定了当前的执行环境,因为方式创建的组件并不自动给我们绑定到当前实例对象。我们可以利用的功能,避免判断逻辑这种充斥在构造函数之中,让代码更优。 React系列---React(一)初识ReactReact系列---React(二)组件的prop和stateReact系列---React(三)组件的生命周期 组件是React...

    Labradors 评论0 收藏0

发表评论

0条评论

Backache

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<