乐趣区

关于dom:react项目如何操作dom

平时在做 react 我的项目过程中难免会遇到一些非凡场景须要去操作 DOM 实现,比方锚点,这篇文章会从两个角度(类组件、函数组件)去总结一些常见操作 DOM 的形式办法。

1、父组件操作子组件 DOM——React.forwardRef

在 16.3 版本之前,没有方法将 ref 传递到一个函数组件之中,然而只有名字不雷同是能够通过 props 传递到子组件。

平凡的 fb 在 react 16.3 中新加了一个 React.forwardRef 函数,使之子组件能够间接接管 ref

function forwardRef<T, P = {}>(render: ForwardRefRenderFunction<T, P>): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>;

interface ForwardRefRenderFunction<T, P = {}> {(props: PropsWithChildren<P>, ref: ForwardedRef<T>): ReactElement | null;
    displayName?: string;
    // explicit rejected with `never` required due to
    // https://github.com/microsoft/TypeScript/issues/36826
    /**
     * defaultProps are not supported on render functions
     */
    defaultProps?: never;
    /**
     * propTypes are not supported on render functions
     */
    propTypes?: never;
}

其实,React.forwardRef 就是一个 HOC,接管一个函数组件,这个函数组件能够接管 ref 参数,说白了,React.forwardRef 的作用就是能够使被包裹组件接管 ref 参数。

这里须要留神,泛型类型 T 指 ref 的类型,P 指 props 类型。

上面举个例子阐明下用法:

// 父组件
const Father = () => {const ref = React.createRef<HTMLDivElement>();
    
    useEffect(() => {if (ref.current) {ref.current.style.fontSize = '16px';}
    })
    
    return <Child ref={ref}></Child>
}

// 子组件
const Child = React.forwardRef<HTMLDivElement, any>((props, ref) => {return <div ref={ref}>child</div>
})

在页面初始渲染完后会批改 Child 组件中 div 文本字体大小。

2、组件内操作 DOM——ref

// React.RefObject<HTMLInputElement>
import React, {useEffect} from 'react';

const InputFocus = () => {const inputRef = React.createRef<HTMLInputElement>();

  useEffect(() => {if (inputRef.current) {inputRef.current.focus();
    }
  })

  return <input type="text" ref={inputRef}/>
}

export default InputFocus;

或者

// ((instance: HTMLInputElement | null) => void)
import React, {useEffect} from 'react';

const InputFocus = () => {

  let inputRef: HTMLDivElement | null = null;

  useEffect(() => {if (inputRef) {inputRef.focus();
    }
  })

  return <input type="text" ref={(el) => inputRef = el}/>
}

export default InputFocus;

如果在类组件内能够如下写:

// React.RefObject<HTMLInputElement>
class InputFocus extends React.Component<{}, {}> {inputRef = React.createRef<HTMLInputElement>();

  componentDidMount(){if (this.inputRef.current) {this.inputRef.current.focus()
    }
  }

  render() {return <input type="text" ref={this.inputRef}/>
  }
}

export default InputFocus;

或者

// ((instance: HTMLInputElement | null) => void)
class InputFocus extends React.Component<{}, {}> {
  inputRef: HTMLInputElement | null = null;

  componentDidMount(){if (this.inputRef) {this.inputRef.focus()
    }
  }

  render() {return <input type="text" ref={(el) => this.inputRef = el}/>
  }
}

export default InputFocus;

这里阐明一下下面两种应用形式,从上图能够得悉 ref 能够接管下面五种类型,能够接管 React.createRef 创立的 React.RefObject<HTMLInputElement> 对象,也能够接管一个函数,参数为绑定该 ref 的元素。

3、

退出移动版