8. React组件三大核心属性之refs

1. 字符串形式的refs

  • 组件内的标签可以通过设置ref属性值来标记自己;
  • 类似于JavaScript中的id属性;
  • 下面例子中 this.refs.input01拿到的是真实dom,不是虚拟dom;
  • react官方未来会弃用这种方式;
  • 弃用原因:就是string类型的refs存在效率问题
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>字符串形式的refs</title>
</head>
<body>
<!--1.准备好容器-->
<div id="root"></div>
<!--2.引入js文件-->
<script type="application/javascript" src="../js/react.development.js"></script>
<script type="application/javascript" src="../js/react-dom.development.js"></script>
<script type="application/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
    //3.1 创建组件
    class Demo extends React.Component{

        render(){
            return (
                <div>
                    <input ref="input01" type="text" placeholder="点击按钮提示左侧input框"/>&nbsp;
                    <button onClick={this.showData_left}>点击弹窗</button>&nbsp;
                    <input ref="input02" onBlur={this.showData_right} type="text" placeholder="失去焦点提示右侧input框"/>
                </div>
            );
        }

        //中间按钮的点击方法
        showData_left = ()=>{
            console.log(this.refs.input01);
            const {input01} = this.refs;
            alert(input01.value);
        }

        //右边input框失去焦点方法
        showData_right = ()=>{
            const input02 = this.refs.input02;
            alert(input02.value);
        }

    }
    //3.2 渲染组件到页面
    ReactDOM.render(<Demo/>, document.getElementById("root"))
</script>
</body>
</html>

2. 内联回调形式的refs

2.1 什么是 回调函数

  • 用户定义的函数
  • 自己没有调用
  • 最终会被执行
  • ()=>{} 箭头函数就是一种回调函数

2.2 内联回调形式ref

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>回调形式的refs</title>
</head>
<body>
<!--1.准备好容器-->
<div id="root"></div>
<!--2.引入js文件-->
<script type="application/javascript" src="../js/react.development.js"></script>
<script type="application/javascript" src="../js/react-dom.development.js"></script>
<script type="application/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
    //3.1 创建组件
    class Demo extends React.Component{

        render(){
            return (
                <div>
                    <input ref={(currentNode)=>{this.input01 = currentNode}} type="text" placeholder="点击按钮提示左侧input框"/>&nbsp;
                    <button onClick={this.showData_left}>点击弹窗</button>&nbsp;
                    <input ref={(c)=>{this.input02 = c}} onBlur={this.showData_right} type="text" placeholder="失去焦点提示右侧input框"/>
                </div>
            );
        }

        //中间按钮的点击方法
        showData_left = ()=>{
            console.log("input01=  ",this.input01);
            const {input01} = this;
            alert(input01.value);
        }

        //右边input框失去焦点方法
        showData_right = ()=>{
            console.log("input02=  ",this.input02);
            const input02 = this.input02;
            alert(input02.value);
        }

    }
    //3.2 渲染组件到页面
    ReactDOM.render(<Demo/>, document.getElementById("root"))
</script>
</body>
</html>

在这里插入图片描述

  • 分析
ref={(currentNode)=>{this.input01 = currentNode}}

在这里插入图片描述
可以在 showData_left(){}中添加一个控制台打印 this ;
发现this自身已经添加了input01和input02属性;
在这里插入图片描述

  • 总结: 回调式ref相当于把所在节点绑定到组件的实例对象上面

2.3 内联回调函数的问题

  • 内联回调函数在react初始化的时候执行一次;
  • 内联回调函数在react执行更新的时候,state状态每次更新都会调用两次;
  • 第一次是清空上一次的内联函数,包括函数的参数,所以会把currentNode赋值为null
ref={(currentNode)=>{this.input01 = currentNode}}

所以在state状态更新的时候出现两次输出,并且第一次 ref 获取的值为null

  • 第二次调用ref为新建函数并调用,属于正常调用;
  • 看实例,如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>回调形式的refs</title>
</head>
<body>
<!--1.准备好容器-->
<div id="root"></div>
<!--2.引入js文件-->
<script type="application/javascript" src="../js/react.development.js"></script>
<script type="application/javascript" src="../js/react-dom.development.js"></script>
<script type="application/javascript" src="../js/babel.min.js"></script>
<script type="application/javascript" src="../js/prop-types.js"></script>
<script type="text/babel">
    //3.1 创建组件
    class Demo extends React.Component{

        render(){
            return (
                <div>
                    <h2>今天天气很{this.state.isHot?"炎热":"凉爽"}</h2>
                    <input ref={(currentNode)=>{this.input01 = currentNode; console.log("ref回调 currentNode=",currentNode)}} type="text" placeholder="点击按钮提示左侧input框"/>&nbsp;
                    <br/><br/>
                    <button onClick={this.showData_left}>点击弹窗</button>&nbsp;
                    <button onClick={this.changeWeather}>切换天气</button>
                </div>
            );
        }

        //中间按钮的点击方法
        showData_left = ()=>{
            // console.log("this = ", this);
            // console.log("input01=  ",this.input01);
            const {input01} = this;
            alert(input01.value);
        }

        state = {isHot:true};

        changeWeather = ()=>{
            const isHot = this.state.isHot;
            this.setState({isHot:!isHot});
            console.log(isHot?"炎热":"凉爽");
        }

    }
    //3.2 渲染组件到页面
    ReactDOM.render(<Demo/>, document.getElementById("root"))
</script>
</body>
</html>

结果如下图:
在这里插入图片描述

3. class绑定函数调用refs

  • 把ref绑定到class的实例上
  • 代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>回调形式的refs</title>
</head>
<body>
<!--1.准备好容器-->
<div id="root"></div>
<!--2.引入js文件-->
<script type="application/javascript" src="../js/react.development.js"></script>
<script type="application/javascript" src="../js/react-dom.development.js"></script>
<script type="application/javascript" src="../js/babel.min.js"></script>
<script type="application/javascript" src="../js/prop-types.js"></script>
<script type="text/babel">
    //3.1 创建组件
    class Demo extends React.Component{

        render(){
            return (
                <div>
                    <h2>今天天气很{this.state.isHot?"炎热":"凉爽"}</h2>
                    <input ref={this.setInput} type="text" placeholder="点击按钮提示左侧input框"/>&nbsp;
                    <br/><br/>
                    <button onClick={this.showData_left}>点击弹窗</button>&nbsp;
                    <button onClick={this.changeWeather}>切换天气</button>
                </div>
            );
        }

        //中间按钮的点击方法
        showData_left = ()=>{
            // console.log("this = ", this);
            // console.log("input01=  ",this.input01);
            const {input01} = this;
            alert(input01.value);
        }

        state = {isHot:true};

        changeWeather = ()=>{
            const isHot = this.state.isHot;
            this.setState({isHot:!isHot});
            console.log(isHot?"炎热":"凉爽");
        }

        setInput = (currentNode)=>{
            this.input01 = currentNode;
            console.log("class绑定方法 ref");
            console.log("setInput  currentNode", currentNode);
        }

    }
    //3.2 渲染组件到页面
    ReactDOM.render(<Demo/>, document.getElementById("root"))
</script>
</body>
</html>
  • 输出结果:
    在这里插入图片描述

4. createRef的调用refs(React官方推荐)

  • React.createRef() 创建一个容器存放当前ref所在节点;
  • 容器和元素节点是一对一的,即一个容器只存一个元素节点;
  • 使用一个元素节点,就要创建一个ref对象;
  • 获取ref所在节点元素 this.myRef.current
  • 官方推荐使用
  • 举例如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>回调形式的refs</title>
</head>
<body>
<!--1.准备好容器-->
<div id="root"></div>
<!--2.引入js文件-->
<script type="application/javascript" src="../js/react.development.js"></script>
<script type="application/javascript" src="../js/react-dom.development.js"></script>
<script type="application/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
    //3.1 创建组件
    class Demo extends React.Component{
        myRef = React.createRef();
        myRef2 = React.createRef();
        render(){
            return (
                <div>
                    <input ref={this.myRef} type="text" placeholder="点击按钮提示左侧input框"/>&nbsp;
                    <button onClick={this.showData_left}>点击弹窗</button>&nbsp;
                    <input ref={this.myRef2} onBlur={this.showData_right} type="text" placeholder="失去焦点提示右侧input框"/>
                </div>
            );
        }

        //中间按钮的点击方法
        showData_left = ()=>{
            console.log("this.myRef = ", this.myRef);
            console.log("this.myRef.current =  ",this.myRef.current);
            alert(this.myRef.current.value);
        }

        //右边input框失去焦点方法
        showData_right = ()=>{
            console.log("myRef2=  ",this.myRef2.current);
            alert(this.myRef2.current.value);
        }

    }
    //3.2 渲染组件到页面
    ReactDOM.render(<Demo/>, document.getElementById("root"))
</script>
</body>
</html>
  • 输出结果如下:
    在这里插入图片描述
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神奇洋葱头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值