React获取DOM系列

2020-05-02  本文已影响0人  发发呆哟

在前端开发过程中,必然有些情况会需要dom元素进行一些节点操作,抛开原生的获取方法,本文将介绍React提供的解决方案,本文所有示例运行版本为react@16.11.0

1. ref

React16.3版本之后React.createRef() API,使用方式如下

class Home extends Component {

    constructor(props){
        super(props)
        this.state = {

        }
        // ref回调方式获取
        this.pRef = null
        this.setCallBackRef = element => {
            this.pRef = element
        }
        this.myNode = React.createRef()
        this.myPara = React.createRef()
    }

    componentDidMount(){
        console.log(this.myNode.current)
        console.log(this.myPara.current)
        // 无current
        console.log(this.pRef)
    }

    render() {
        return <div>
            <Para ref={this.myPara} />
            <p ref={this.setCallBackRef}>123</p>
            <p ref={this.myNode}>{this.props.number}</p>
        </div>
    }
}

当 ref 被传递给 render 中的元素时,对该节点的引用可以在 ref 的 current 属性中被访问。
ref 的值根据节点的类型而有所不同:

备注:ref在componentDidMountcomponentDidUpdate 生命周期钩子触发前更新。

上述代码运行结果如下 ref-运行结果.jpg

可以看出,我们在挂在到自定义组件时,获取到了这个组件的实例,可以获取到它的props,context以及自定义函数,那么有意思的事情就来了,我们这时可以再父组件中调用子组件的函数来完成某些业务场景

class Para extends React.Component {

    close = () => {
        alert(1)
    }

    render(){
        return <div>
            <p>1</p>
        </div>
    }
}
class Home extends Component {

    constructor(props){
        super(props)
        this.myPara = React.createRef()
    }

    render() {
        return <div>
            <Para ref={this.myPara} />
            <button onClick={()=>this.myPara.current.close()}>close</button>
        </div>
    }
}
运行结果如下 父组件调用子组件实例函数.jpg

这个操作可以实现有趣的功能,可以好好玩一下,特别是在业务组件里。

2. findDOMNode()

reactDom提供了一个api,可以让我们获取dom节点,不过大多数情况下不推荐使用,且在严格模式下已经被弃用。
弃用原因:findDOMNode 只返回第一个子节点,但是使用 Fragments,组件可以渲染多个 DOM 节点。findDOMNode 是一个只读一次的 API。调用该方法只会返回第一次查询的结果。如果子组件渲染了不同的节点,则无法跟踪此更改。因此,findDOMNode 仅在组件返回单个且不可变的 DOM 节点时才有效。

class Home extends Component {

    constructor(props){
        super(props)
        this.state = {

        }
        // ref回调方式获取
        this.pRef = null
        this.setCallBackRef = element => {
            this.pRef = element
        }
        this.myNode = React.createRef()
        this.myPara = React.createRef()
    }

    // 获取实例化组件dom
    getComponent = () => {
        const node = findDOMNode(this.myPara.current)
        console.log(node)
    }

    componentDidMount(){
        console.log(this.myNode.current)
        console.log(this.myPara.current)
        // 无current
        console.log(this.pRef)
    }

    render() {
        return <div>
            <Para ref={this.myPara} />
            <p ref={this.setCallBackRef}>123</p>
            <p ref={this.myNode}>{this.props.number}</p>
            <button onClick={()=>this.myPara.current.close()}>close</button>
            <button onClick={this.getComponent}>getNode</button>
        </div>
    }
}

ReactDOM下的几个api都很有趣,回头分析一下,埋个坑。

3.useRef

react@16.8版本之后,使用hook,hook提供了useRef来获取dom,注意:返回的 ref 对象在组件的整个生命周期内保持不变(current是变化的),相对React.createRef()在生命周期过程中是一直变化的。代码如下

import React, { useRef, useEffect } from 'react';
import Para from './Para'

const UseRef = () => {
    const myNode = useRef(null);
    const myPara = useRef(null);

    useEffect(() => {
        console.log(myNode.current)
        console.log(myPara.current)
    }, []);

    return <div>
        <p ref={myNode}>123</p>
        <Para ref={myPara} />
    </div>
}

export default UseRef;
上一篇 下一篇

猜你喜欢

热点阅读