React学习-三大属性之ref属性

一是什么

二如何使用

三 引用场景

 

 

一是什么?

React中的refs提供了一种方式,允许我们访问dom节点或者是在render方法中创建的react元素。

它的本质是ReactDOM.render返回的组件实例,如果是渲染组件返回的就是组件实例,如果是渲染DOM,然回的就是dom节点。

 

 

二如何使用?

创建ref的形式有三种:

1.传入字符串,使用的时候通过 this.refs.传入的字符串 的格式来获取对应的元素,如下:

<!DOCTYPE html>
<html>
    <head>
        <title>字符串形式的ref</title>
    </head>

    <body>
        <!-- 1.创建一个容器 -->
        <div id="test"></div>
        <!-- 2.导入核心包,必须按照顺序来导入 -->
        <script type="text/javascript" src="../js/react.development.js"></script>
        <script
            type="text/javascript"
            src="../js/react-dom.development.js"
        ></script>
        <script type="text/javascript" src="../js/babel.min.js"></script>

        <div id="test"></div>

        <!-- 3.编写代码:注意使用的type是text/babel -->
        <!-- React里面的是使用refs,Vue里面是使用$refs,refs拿的是真实的dom节点,而不是虚拟的dom -->
        <!-- 字符串形式的ref并不推荐使用,因为效率问题,可能在后面的版本中弃用 -->
        <script type="text/babel">
            class Dome extends React.Component {
                // 注意如果要将方法里面的this绑定到组件实例上,需要的格式是使用=号加上箭头函数
                showData1 = () => {
                    alert(this.refs.input1.value)
                }
                showData2 = () => {
                    alert(this.refs.input2.value)
                }
                render() {
                    return (
                        <div>
                            <input type='text' ref='input1' />
                            {/*jsx里面的事件和原生的有些不同,原生的是onclick ,jsx里面的是onClick*/}
                            <button ref='button1' onClick={this.showData1}>
                                点击我显示输入框的数据
                            </button>
                            <input
                                type='text'
                                ref='input2'
                                placeholder='失去焦点显示数据'
                                onBlur={this.showData2}
                            />
                        </div>
                    )
                }
            }
            ReactDOM.render(<Dome />, document.getElementById('test'))
        </script>
    </body>
</html>

 

2.传入对象,对象是通过 React.createRef() 方法创建出来的,一个对象只能包含一个dom,使用时候获取到创建的对象中存在current属性就是对应的元素,如下:

<!DOCTYPE html>
<html>
    <head>
        <title>字符串形式的ref</title>
    </head>

    <body>
        <!-- 1.创建一个容器 -->
        <div id="test"></div>
        <!-- 2.导入核心包,必须按照顺序来导入 -->
        <script type="text/javascript" src="../js/react.development.js"></script>
        <script
            type="text/javascript"
            src="../js/react-dom.development.js"
        ></script>
        <script type="text/javascript" src="../js/babel.min.js"></script>

        <div id="test"></div>

        <script type="text/babel">
            class Dome extends React.Component {
                myRef1 = React.createRef() // 创建一个存放dom的ref盒子,但是一个只能存放一个dom,如果多次使用同一个,后面的会覆盖前面的
                myRef2 = React.createRef()
                showData1 = () => {
                    let input = this.myRef1.current
                    alert(input.value)
                }
                showData2 = () => {
                    let input = this.myRef2.current
                    alert(input.value)
                }
                render() {
                    return (
                        <div>
                            <input type='text' ref={this.myRef1} />
                            <button onClick={this.showData1}>点击我显示输入框的数据</button>
                            <input
                                type='text'
                                ref={this.myRef2}
                                placeholder='失去焦点显示数据'
                                onBlur={this.showData2}
                            />
                        </div>
                    )
                }
            }
            ReactDOM.render(<Dome />, document.getElementById('test'))
        </script>
    </body>
</html>

 

3.传入回调函数,该函数会在DOM挂载的时候进行回调,这个函数会传入一个元素对象,可以自己保存,使用的时候,直接拿到之前保存的元素对象就可以了

<!DOCTYPE html>
<html>
    <head>
        <title>字符串形式的ref</title>
    </head>

    <body>
        <!-- 1.创建一个容器 -->
        <div id="test"></div>
        <!-- 2.导入核心包,必须按照顺序来导入 -->
        <script type="text/javascript" src="../js/react.development.js"></script>
        <script
            type="text/javascript"
            src="../js/react-dom.development.js"
        ></script>
        <script type="text/javascript" src="../js/babel.min.js"></script>

        <div id="test"></div>

        <!-- 3.编写代码:注意使用的type是text/babel -->
        <!-- React里面的是使用refs,Vue里面是使用$refs,refs拿的是真实的dom节点,而不是虚拟的dom -->
        <script type="text/babel">
            class Dome extends React.Component {
                // 注意如果要将方法里面的this绑定到组件实例上,需要的格式是使用=号加上箭头函数
                showData1 = () => {
                    let { input1 } = this // 注意:这个时候是从当前组件实例上拿去dom节点,而而不是从refs上
                    alert(input1.value)
                }
                showData2 = () => {
                    let { input2 } = this // 注意:这个时候是从当前组件实例上拿去dom节点,而而不是从refs上
                    alert(input2.value)
                }
                render() {
                    return (
                        <div>
                            {/*
                                回调形式的ref
                                    c是当前的dom节点,将当前节点赋值给组件实例的input1上,注意这里的this的是组件实例
                             */}
                            <input type='text' ref={(c) => (this.input1 = c)} />
                            {/*jsx里面的事件和原生的有些不同,原生的是onclick ,jsx里面的是onClick*/}
                            <button onClick={this.showData1}>点击我显示输入框的数据</button>
                            <input
                                type='text'
                                ref={(c) => (this.input2 = c)}
                                placeholder='失去焦点显示数据'
                                onBlur={this.showData2}
                            />
                        </div>
                    )
                }
            }
            ReactDOM.render(<Dome />, document.getElementById('test'))
        </script>
    </body>
</html>

 

如果 ref 回调函数是以内联函数的方式定义的,在更新过程中它会被执行两次,第一次传入参数 null,然后第二次会传入参数 DOM 元素。这是因为在每次渲染时会创建一个新的函数实例,所以 React 清空旧的 ref 并且设置新的。通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题,但是大多数情况下它是无关紧要的。

 

4传入hook,hook是通过useRef()方式来创建的,使用时候通过生成hook对象的current属性就是对应的元素。(Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。React的三大特性ref,state,props其中的ref和state是类式组件特有的,而函数式组件式没有的

function App(props) {
   const ref = useRef()
       return (
            <div>
                <div ref={myRef}>1111</div>
            </div>
        )
}

 

获取ref属性也式通过hook对象的current属性来获取。

const node = myref.current;

 

需要注意的是:不能在函数式组件上使用ref属性,因为他们并没有实例。

 

三 应用场景?

过多的使用refs,会使组件的实例或者式DOM结构暴露,违反了封装组件的原则。

例如,在Dialog组件里面暴露了open和close方法,通常我们可以传递一个isOpen属性来控制弹窗的显示

下面的场景可以使用refs:

(1)对dom元素的焦点控制,内容选择,控制。

(2)对dom元素的内容设置和媒体播放

(3)对dom元素的操作和对组件的实例的操作

(4) 集成第三方的DOM库

 

posted @ 2022-04-05 14:53  颗就完了  阅读(642)  评论(0编辑  收藏  举报