平时在做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、