React Refs的使用

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

Refs使用场景:

  • 管理焦点,文本选择或媒体播放。
  • 触发强制动画。
  • 集成第三方 DOM 库。
  1. 访问Dom常用方法

使用 React.createRef() 创建

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
class CustomTextInput extends React.Component { 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> <input type="text" ref={this.textInput} /> <input type="button" value="Focus the text input" onClick={this.focusTextInput} /> </div> ); } } export default CustomTextInput

refs的另一种方法 回调refs

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
class CustomTextInput extends React.Component { 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> <input type="text" ref={this.setTextInputRef} /> <input type="button" value="Focus the text input" onClick={this.focusTextInput} /> </div> ); } } export default CustomTextInput

利用回调ref来控制获取子组件dom

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
function CustomTextInput(props) { return ( <div> <input ref={props.inputRef} /> </div> ); } class Parent extends React.Component { inputElement=null componentDidMount(){ this.inputElement.value="我用ref控制下CustomTextInput" } render() { return ( <CustomTextInput inputRef={el =>{console.log(el); this.inputElement = el}} /> ); } } export default Parent

这个相当于把inputRef这个函数作为属性传给CustomTextInput,this还是绑定在父组件,从而间接获取input的ref

默认情况下,你不能在函数组件上使用 ref 属性,因为它们没有实例: 如果要在函数组件中使用 ref,你可以使用 forwardRef(可与 useImperativeHandle 结合使用),或者可以将该组件转化为 class 组件。

refs转发

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
const FancyButton = React.forwardRef((props, ref) => ( <button ref={ref} className="FancyButton" {...props}> {props.children} </button> )); class Parent extends React.Component { fancyRef = React.createRef(); fancyClick = () => { console.log("我拿到的是button元素", this.fancyRef.current) } render() { return ( <div> <FancyButton ref={this.fancyRef} onClick={this.fancyClick} >Fancy Button </FancyButton> </div> ) } } export default Parent

官方解释:

  1. 我们通过调用 React.createRef 创建了一个 React ref 并将其赋值给 ref 变量。
  2. 我们通过指定 ref 为 JSX 属性,将其向下传递给
  3. React 传递 ref 给 forwardRef 内函数 (props, ref) => ...,作为其第二个参数。
  4. 我们向下转发该 ref 参数到
  5. 当 ref 挂载完成,ref.current 将指向

注意

第二个参数 ref 只在使用 React.forwardRef 定义组件时存在。常规函数和 class 组件不接收 ref 参数,且 props 中也不存在 ref。

Ref 转发不仅限于 DOM 组件,你也可以转发 refs 到 class 组件实例中。

下面是高阶组件使用Ref转发

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
//这是一个包装函数 能打印出输入的值 const Decorate = InputComponent => { const forwardRef = (props, ref) => { const print = () => console.log("ref当前的值", ref.current.value); return <InputComponent forwardedRef={ref} onChange={print} {...props} />; }; return React.forwardRef(forwardRef); }; //包装函数将转发ref属性传给需要包装的组件 const TextInput = ({ forwardedRef, children, ...rest }) => ( <div> <input ref={forwardedRef} {...rest} /> {children} </div>); const InputField = Decorate(TextInput); class CustomTextInput extends React.Component { render() { const inputRef = React.createRef(); return <InputField ref={inputRef}>children</InputField >; } } export default CustomTextInput

最后 勿过度使用Refs 多考虑状态提升,在 React 中,将多个组件中需要共享的 state 向上移动到它们的最近共同父组件中,便可实现共享 state。这就是所谓的“状态提升”。

总之,ref在实际中还是用的不是很多,特别是转发ref的使用,主要借此来记录ref的使用

本文主要参考 官方文档

(完)
4连锤,好痛!
保本出?
React Refs的使用
Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素。
闭包
Js神兽闭包
GitHub Copilot
大大提升你写代码的效率
简单讲讲Vuex
Vue状态管理工具
双指针:回文字符串(680)
删除一个字符,判断是否能构成回文字符串。所谓的回文字符串,是指具有左右对称特点的字符串,例如 "abcba" 就是一个回文字符串。
等待你的评论