平時在作react項目過程當中不免會遇到一些特殊場景須要去操做DOM完成,好比錨點,這篇文章會從兩個角度(類組件、函數組件)去總結一些常見操做DOM的方式方法。react
在16.3版本以前,沒有辦法將ref傳遞到一個函數組件之中,可是隻要名字不相同是能夠經過props傳遞到子組件。git
偉大的fb在react 16.3中新加了一個React.forwardRef函數,使之子組件能夠直接接收refgithub
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文本字體大小。ui
// 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;
或者this
// ((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;
若是在類組件內能夠以下寫:spa
// 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;
或者code
// ((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的元素。