React 学习笔记(10)组件三大核心属性之三:refs与事件处理

206 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情

前言

前面学习了组件两个重要属性的基本用法,今天学习最后一个:refs

什么是refs

ref 就是给我们操作真实 dom 提供了一个入口,在 render() 输出的组件使用refs与组件dom绑定,从而让React有直接去操作页面的真实DOM的能力,一般情况下很少会用到这个东西,一般是处理一些dom事件,失去焦点,获得焦点或者文本选择或媒体播放,看看下面的代码来认识refs

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>学习React</title>
</head>

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

    <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>
    <script type="text/javascript" src="../js/prop-types.js"></script>
    <script type="text/babel">
        class Translate1 extends React.Component {
            state = { isShow: false }  //初始化状态
            showData = () => {
                this.state.isShow = !this.state.isShow  //状态不可以直接更改
                this.setState({ state: this.state.isShow })
                console.log(this);
            }
            showInput = () => {
                const { inputs } = this.refs
                if (inputs.value == '神话') {
                    alert('回答正确, 您输入的是:' + inputs.value)
                } else {
                    alert('回答错误, 您输入的是:' + inputs.value)
                }
            }

            render() {
                const { crow } = this.props
                return (
                    <div>
                        <ul>
                            <li>我是云南的</li>
                            <li>云南怒江的</li>
                            <li>怒江泸水市</li>
                            <li>泸水市六库</li>
                            <li>六库傈僳族</li>
                            <li>傈僳族是这样叫</li>
                            <li>乌鸦叫做 {this.state.isShow ? '阿南' : '__'}</li>
                            <li>青蛙叫做{this.state.isShow ? '欧巴' : '__'}</li>
                            <li>老公叫做{this.state.isShow ? '搓趴' : '__'}</li>
                            <li>老婆叫做{this.state.isShow ? '搓嘛' : '__'}</li>
                            <li>香菜叫做{this.state.isShow ? '野穴' : '__'}</li>
                            <li>红薯叫做{this.state.isShow ? '阿梦' : '__'}</li>
                            <li>老虎叫做{this.state.isShow ? '喇嘛' : '__'}</li>
                            <li>黄瓜叫做{this.state.isShow ? '阿布' : '__'}</li>
                            <li>南瓜叫做{this.state.isShow ? '阿普' : '__'}</li>
                            <li>鸡蛋叫做{this.state.isShow ? '嘛啊耶夫' : '__'}</li>
                        </ul>
                        <button onClick={this.showData}>瞄一眼</button>
                        <div>甘肃不大,创造__</div>
                        <div>
                            请输入答案:<input ref='inputs' onBlur={this.showInput}></input></div>
                    </div>
                )
            }
        }

        ReactDOM.render(<Translate1 />, document.getElementById('test'))
    </script>
</body>
</html>

动画11.gif

注意

字符串形式的refs已不被React推荐,React官网说:string类型的refs存在一些问题,它已过时并可能在未来的版本被移除,原因是因为字符串类型的refs存在一些效率问题。官网解释的时候指向了GitHub项目的pullRequest讨论区内。

image.png

回调函数式的refs

修改input标签和对应的失去焦点的函数

               请输入答案:<input ref={c=>this.input = c} onBlur={this.showInput}></input></div>
            showInput = () => {
                const { inputs } = this
                if (inputs.value == '神话') {
                    alert('回答正确, 您输入的是:' + inputs.value)
                } else {
                    alert('回答错误, 您输入的是:' + inputs.value)
                }
            }

image.png 同样也能实现上面字符串refs的功能,ref回调函数是以内联函数的方式定义的,在更新的过程中会被执行两次,第一次初始化传入的参数为null,第二次才会传入参数DOM元素。因为在每次渲染时会创建一个新的函数实例,所以React会清空就得ref并生成新的。通过回调定义成class的绑定函数的方式可以避免这个问题。

此时回调形式的refs还不是最优解。接下来做一个class的绑定函数例子

补充知识 内联函数

内联函数例子:

    var myfunc = function f() {
        console.log(myfunc == f); // true
    }

    myfunc(); //true
    console.log(typeof f); // undefined
    f(); // Uncaught ReferenceError: f is not defined

特点:

内联函数的名称只能在自身函数内部才可以使用。使用内联方式调用,其本质和函数表达式没有太大不同,区别就是内联命名函数在函数内部提供了一个仅可供自身调用的函数指针,该指针指向函数自身。

refs class的绑定函数

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>学习React</title>
</head>

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

    <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>
    <script type="text/javascript" src="../js/prop-types.js"></script>
    <script type="text/babel">
        class Translate1 extends React.Component {
            state = { isYunNan: false }  //初始化状态
            saveInput = (c) => {  
                this.input1 = c;  
                console.log(c)
                
            }
            showInfo = ()=>{
                const {input1} = this //class的绑定函数
                alert(input1.value)
            }
            changePlace=()=>{
                
                const {isYunNan} = this.state  //状态不可以直接更改
                console.log(isYunNan)
                this.setState({ isYunNan: !isYunNan })
            }

            render() {
                const { isYunNan } = this.state 
                return (
                    <div>
                        <h2>我{isYunNan ? '是' : '不是'}云南的</h2>
                      
                        <div>
                            请输入答案:<input ref={this.saveInput} type='text'></input>
                        </div>
                        <button onClick={this.changePlace}>切换住址</button>
                        <button onClick={this.showInfo}>显示输入</button>
                    </div>
                )
            }
        }

        ReactDOM.render(<Translate1 />, document.getElementById('test'))
    </script>
</body>

</html>

saveInput这个方法已经绑定到实例自身了,上面内联函数直接写在了rander里面,这里的内联函数写在组件里面。