更新时间:2019年07月26日 11时16分11秒 来源:黑马程序员论坛
使用 React 时,我们的默认思维方式应该是 不会强制修改 DOM ,而是通过传入 props 重新渲染组件。但是,有些情况却无法避免修改 DOM 。 React 中的 Refs 提供了一种访问 render() 方法中创建的 React 元素(或 DOM 节点)的方法。 当父组件需要与子组件交互时,我们通常使用 props 来传递相关信息。 但是,在某些情况下,我们可能需要修改子项,而不用新的props 重新呈现 (re-rendering) 它。 这时候就需要 refs 出场了。 我什么时候应该使用 Refs ?我们建议在以下情况下使用 refs:
所以一旦我们确定我们真的应该使用 refs,我们需要如何使用它们呢? 在 React 中使用 Refs您可以通过多种方式使用 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 <div ref={this.firstRef} />; }} 如上所示:
接下来,让我们看一个在 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 <input> ref // with the `textInput` that we created in the constructor return ( <div> <input type="text" ref={this.textInput} /> <input type="button" value="Focus the text input" onClick={this.focusTextInput} /> </div> ); }} 在上面的代码块中,我们构建了一个按钮,当单击它时,该页面会自动聚焦在输入框上。 首先,我们在构造方法中创建一个 ref 实例,并将其赋值给 this.textInput,然后通过 ref 属性将其分配给 input 元素。 [HTML] 纯文本查看 复制代码 <input type="text" ref={this.textInput} /> 注意,当 ref 属性被一个 HTML 元素使用时(比如当前示例中的 input 元素),在 constructor 中使用 React.createRef() 创建的 ref 会接收来自底层 DOM 元素的 current 值。
这意味着访问 DOM 值,我们需要写这样的东西: [JavaScript] 纯文本查看 复制代码 this.textInput.current; 第二个元素是一个按钮,点击它之后会自动聚焦到第一个输入框上面。我们为 onClick 属性设置了 this.focusTextInput 函数。 [JavaScript] 纯文本查看 复制代码 <input 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); 在这个例子中,我们将看到如何为 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 <input> ref // with the `textInput` that we created in the constructor return ( <div> <form onSubmit={e => this.handleSubmit(e)}> <input type="text" ref={this.textInput} /> <button>Submit</button> </form> </div> ); }} 同样,我们使用该 React.createRef() 函数创建一个 ref 实例,然后将它分配给实例变量 this.textInput。 在 render 函数中,我们希望读取 form 下输入框的值。我们如何读取这个值? 通过为 input 指定一个 ref ,然后读取 ref 的值。 [JavaScript] 纯文本查看 复制代码 <input type="text" ref={this.textInput} /> 点击提交按钮,上面示例中 form 元素会通过 onSubmit 方法,调用 this.handleSubmit 函数 ,并在控制台打印输入框中的信息。 [JavaScript] 纯文本查看 复制代码 handleSubmit = e => { e.preventDefault(); console.log(this.textInput);};
在上面示例中,我们打印了 this.textInput ,在控制台可以看到一个 ref 对象。 [JavaScript] 纯文本查看 复制代码 > 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 ( <div> <form onSubmit={e => this.handleSubmit(e)}> <input type="text" ref={this.setTextInputRef} /> <button>Submit</button> </form> </div> ); }} 上面的示例中,我们将 input 标签的 ref 设置为 this.setTextInputRef。 当组件安装时,React 会将 DOM 元素传递给 ref 的回调;当组件卸载时,则会传递 null。(ref 回调会在 componentDidMount 和 componentDidUpdate 生命周期之前调用。) String Ref(已过时)还有另一种设置 refs 的方法,但它被认为是过时的,可能很快就会被弃用。但是你可能会在其他人的代码中看到它,所以这里说一下。 使用 string refs,你将会看到这样的 input 标签: [HTML] 纯文本查看 复制代码 <input type="text" ref="textInput" /> 然后,我们可以在组建上得到这样的值:this.refs.textInput.value - 但是,再次声明,这不应该在新代码中使用,因为这个 API 将被弃用。 转发 Refs (Forwarding Refs)Ref forwarding 是一种将 ref 通过组件传递给其子节点的技术。它对于可复用组件库和高阶组件(HOC)等情况非常有用。 您可以使用 React.forwardRef 函数将 ref 转发到组件。我们来看下面的例子: [JavaScript] 纯文本查看 复制代码 // Ref.jsconst TextInput = React.forwardRef((props, ref) => ( <input type="text" placeholder="Hello World" ref={ref} />));const inputRef = React.createRef();class CustomTextInput extends React.Component { handleSubmit = e => { e.preventDefault(); console.log(inputRef.current.value); }; render() { return ( <div> <form onSubmit={e => this.handleSubmit(e)}> <TextInput ref={inputRef} /> <button>Submit</button> </form> </div> ); }} Ref forwarding 允许组件接收一个 ref ,并将它向下传递(换句话说,“转发”它)给子组件。 在上面的示例中,我们使用 input 标签创建了一个名为 TextInput 的组件。那么,我们如何将 ref 传递或转发到 input 标签呢? 首先,我们使用下面的代码创建一个 ref : [JavaScript] 纯文本查看 复制代码 const inputRef = React.createRef(); 然后,我们将 ref 通过为组件 <TextInput ref={inputRef}> 指定一个同名的 JSX 的属性,将 ref 向下传递。然后 React 将会把 ref 作为第二个参数转发给 forwardRef 函数。 接下来,我们将此 ref 参数转发给 <input ref={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 <InputComponent forwardedRef={ref} onChange={onType} {...props} />; }; return React.forwardRef(forwardRef);}; 这里有一个名为 Input 的高阶组件 ,它接受 InputComponent 作为参数。当用户输入的时候,他还会将 ref 的值在控制台打印。 在 Input 高阶组件内,forwardRef 函数会返回 InputComponent。forwardRef 函数中所包含的 ref 参数,是由 React.forwardRef 函数创建的。 高阶组件最终会将包装好的组件作为值返回。 接下来,我们创建一个组件,将 input 作为子组件包含进来。 [JavaScript] 纯文本查看 复制代码 const TextInput = ({ forwardedRef, children, ...rest }) => ( <div> <input ref={forwardedRef} {...rest} /> {children} </div>); 上面的组件会将 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 <InputField ref={inputRef} />; }} 最后,将 TextInput 传入 Input 高阶组件,会返回一个 InputField component。 创建一个 ref ,并作为参数传递给 InputField 组件。 结论与通过 props 和 state 不同,Refs 是一种将数据传递给特定子实例的好方法。 你必须要小心,因为 refs 操纵实际的 DOM,而不是虚拟的 DOM,这与 React 思维方式相矛盾。因此,虽然 refs 不应该是通过应用程序流动数据的默认方法,但是当您需要时,它们是可以从 DOM 元素读取数据的好方法。 点击查看更多精彩前端资源 点击有惊喜 |
推荐了解热门学科
java培训 | Python人工智能 | Web前端培训 | PHP培训 |
区块链培训 | 影视制作培训 | C++培训 | 产品经理培训 |
UI设计培训 | 新媒体培训 | 产品经理培训 | Linux运维 |
大数据培训 | 智能机器人软件开发 |
传智播客是一家致力于培养高素质软件开发人才的科技公司,“黑马程序员”是传智播客旗下高端IT教育品牌。自“黑马程序员”成立以来,教学研发团队一直致力于打造精品课程资源,不断在产、学、研3个层面创新自己的执教理念与教学方针,并集中“黑马程序员”的优势力量,针对性地出版了计算机系列教材50多册,制作教学视频数+套,发表各类技术文章数百篇。
传智播客从未停止思考
传智播客副总裁毕向东在2019IT培训行业变革大会提到,“传智播客意识到企业的用人需求已经从初级程序员升级到中高级程序员,具备多领域、多行业项目经验的人才成为企业用人的首选。”
中级程序员和初级程序员的差别在哪里?
项目经验。毕向东表示,“中级程序员和初级程序员最大的差别在于中级程序员比初级程序员多了三四年的工作经验,从而多出了更多的项目经验。“为此,传智播客研究院引进曾在知名IT企业如阿里、IBM就职的高级技术专家,集中研发面向中高级程序员的课程,用以满足企业用人需求,尽快补全IT行业所需的人才缺口。
何为中高级程序员课程?
传智播客进行了定义。中高级程序员课程,是在当前主流的初级程序员课程的基础上,增加多领域多行业的含金量项目,从技术的广度和深度上进行拓展。“我们希望用5年的时间,打造上百个高含金量的项目,覆盖主流的32个行业。”传智播客课程研发总监于洋表示。
黑马程序员热门视频教程【点击播放】
Python入门教程完整版(懂中文就能学会) | 零起点打开Java世界的大门 |
C++| 匠心之作 从0到1入门学编程 | PHP|零基础入门开发者编程核心技术 |
Web前端入门教程_Web前端html+css+JavaScript | 软件测试入门到精通 |