最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • React--10: 组件的三大核心属性3:refs与事件处理

    正文概述 掘金(csdn来挖墙脚)   2021-08-18   481

    这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战

    1. 字符串形式的ref

    首先这种形式是不推荐使用的。

    过时 API:String 类型的 Refs:

    如果你之前使用过 React,你可能了解过之前的 API 中的 string 类型的 ref 属性,例如 "textInput"。你可以通过 this.refs.textInput 来访问 DOM 节点。我们不建议使用它,因为 string 类型的 refs 存在一些效率上的问题。它已过时并可能会在未来的版本被移除(16.8版本还没有移除)。

    React--10: 组件的三大核心属性3:refs与事件处理

    点击按钮获取输入框数据

    按照我们原生的写法,怎么在函数中获得输入框中的内容呢?首先给输入框一个id,然后通过getElementById 获得输入框中的值。

    class Demo extends React.Component{
        showData = ()=>{
            let value = document.getElementById('input1').value
            console.log(value)
        }   
        render(){
            return(
                <div>
                    <input  type="text" placeholder="点击按钮提示数据"/>&nbsp;
                    <button onClick={this.showData}>点击提示数据</button>&nbsp;
                    <input type="text" placeholder="失去焦点提示数据" />&nbsp;
                </div>
            )
        }
    }
    

    但是在React中去使用原生不是很好。因此ref就出现了。给input标签中添加ref属性(就类似于id)

    React--10: 组件的三大核心属性3:refs与事件处理

    此时输出的this是类的实例 。 我们发现了refs中有 input1,是键值对类型。

    React--10: 组件的三大核心属性3:refs与事件处理

    打印、获取输入框的内容

        showData = ()=>{
           console.log(this.refs.input1.value)
           const {input1} = this.refs
        }   
    

    失去焦点提示数据

    <input type="text"  ref="input2" 
    onBlur={this.showData2}  placeholder="失去焦点提示数据" />&nbsp;
      showData2 =()=>{
            const {input2} = this.refs
            alert(input2.value)
        }
    

    React--10: 组件的三大核心属性3:refs与事件处理

    总结

    refs 是实例上的属性。ref就像原生js的id,可以理解为打标签。

    import React from 'react';
    import ReactDOM from 'react-dom';
    import PropTypes from 'prop-types';
    import './index.css';
    class Demo extends React.Component{
        showData = ()=>{
           console.log(this.refs.input1.value)
        }   
        showData2 =()=>{
            const {input2} = this.refs
            alert(input2.value)
        }
        render(){
            return(
                <div>
                    <input ref="input1" type="text" placeholder="点击按钮提示数据"/>&nbsp;
                    <button onClick={this.showData}>点击提示数据</button>&nbsp;
                    <input type="text"  ref="input2" onBlur={this.showData2}  placeholder="失去焦点提示数据" />&nbsp;
                </div>
            )
        }
    }
    ReactDOM.render(<Demo/>, document.getElementById('root'))
    

    2. 回调形似的ref

    ref 中写回调函数,传入的参数是什么呢?我们打印看一下。

      <input ref={(a)=>{console.log(a)}} type="text" placeholder="点击按钮提示数据"/>
    

    可以看到打印出来的是ref所处节点

    React--10: 组件的三大核心属性3:refs与事件处理 我们接下来把ref所处节点挂载到实例自身上,并取了个名字input1(剪头函数的 this 是其外部的 this,也就是render的实例,也就是 Demo实例) React--10: 组件的三大核心属性3:refs与事件处理

    完整代码:

    class Demo extends React.Component{
        showData = ()=>{
           const {input1} = this
           alert(input1.value)
        }   
        showData2 =()=>{
            console.log(this)
            const {input2} = this
            alert(input2.value)
        }
        render(){
            return(
                <div>
                    <input ref={(a)=>{this.input1 = a}} type="text" placeholder="点击按钮提示数据"/>&nbsp;
                    <button onClick={this.showData}>点击提示数据</button>&nbsp;
                    {/* 剪头函数只有一个参数的时候可以简写 */}
                    <input type="text"  ref={c=>this.input2=c} onBlur={this.showData2}  placeholder="失去焦点提示数据" />&nbsp;
                </div>
            )
        }
    }
    

    回调执行次数问题

    关于回调 refs 的说明

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

    内联的写法

    首先什么是内联函数?如下ref中的函数就是内联函数。

       <input ref={(currentNode)=>{this.input1 = currentNode;console.log("currentNode",currentNode)}} type="text" placeholder="点击按钮提示数据"/>&nbsp;
    

    那么什么又算更新过程呢?

    我点击按钮输出文本框的内容算吗?这只是交互,并不算是更新。

    还记得我们前几篇文章用到的点击按钮切换天气的例子吗?我们在这里再次用到它。也就是用setState的使用。

        state = {
            isHot:true
        }
        showInfo = ()=>{
          const {input1} = this
          alert(input1.value)
        }
        changeWeather = ()=>{
            // 获取原来状态
            const {isHot} = this.state
            this.setState({isHot:!isHot})
        }
        render(){
            const {isHot} = this.state
            return(
                <div>
                    <h1>今天天气很{isHot?"炎热":"凉爽"}</h1>
                    <input ref={(currentNode)=>{this.input1 = currentNode;console.log("currentNode",currentNode)}} type="text" placeholder="点击按钮提示数据"/><br></br>
                    <button onClick={this.showInfo}>点击提示数据</button><br></br>
                    <button onClick={this.changeWeather}>点击改变天气</button><br></br>
                </div>
            )
        }
    

    点击改变天气按钮 我们发现 打印了两次,并且第一次是null,第二次才是节点。(点击改变天气使页面进行了更新) React--10: 组件的三大核心属性3:refs与事件处理

    ?

    当更新页面时,render方法就会被调用一次。然后<input ref={(currentNode)=>{this.input1 = currentNode;console.log("currentNode",currentNode)}} type="text" placeholder="点击按钮提示数据"/>代码就会执行,它又会发现ref,而且还是函数式的ref。这个函数又是一个新的函数了,之前的函数被执行完释放了。它并不确定之前的函数执行了什么,因此为了清空上一次调用的函数,传了null将第函数清空,第二次才把当前节点传进来。

    怎么解决呢??

    class 的绑定函数的写法

    通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题,但是大多数情况下它是无关紧要的。 this.saveInput

    class Demo extends React.Component{
        state = {
            isHot:true
        }
        showInfo = ()=>{
          const {input1} = this
          alert(input1.value)
        }
        changeWeather = ()=>{
            // 获取原来状态
            const {isHot} = this.state
            this.setState({isHot:!isHot})
        }
        saveInput = (c)=>{
            this.input1 = c
            console.log("c",c)
        }
        render(){
            const {isHot} = this.state
            return(
                <div>
                    <h1>今天天气很{isHot?"炎热":"凉爽"}</h1>
                    {/* <input ref={(currentNode)=>{this.input1 = currentNode;console.log("currentNode",currentNode)}} type="text" placeholder="点击按钮提示数据"/><br></br> */}
                    <input ref={this.saveInput} type="text" placeholder="点击按钮提示数据"/><br></br> 
                    <button onClick={this.showInfo}>点击提示数据</button><br></br>
                    <button onClick={this.changeWeather}>点击改变天气</button><br></br>
                </div>
            )
        }
    }
    

    现在怎么点击都不会频繁的调用 saveInput 了,因为 saveInput已经放在实例自身了。

    当然直接写成内联的也问题不太。内联的写法是比较常见的。

    3. CreateRef

    使用 createRef API

    React.createRef调用后可以返回一个容器,该容器可以存储被ref标识的节点。但是只能存放一个

    class Demo extends React.Component{
        // React.createRef调用后可以返回一个容器,该容器可以存储被ref标识的节点
        myRef = React.createRef()
        state = {
            isHot:true
        }
        showData = ()=>{
            console.log(this.myRef)
        }
        render(){
            const {isHot} = this.state
            return(
                <div>
                    <h1>今天天气很{isHot?"炎热":"凉爽"}</h1>
                    <input ref={this.myRef} type="text" placeholder="点击按钮提示数据"/><br></br> 
                    <button onClick={this.showData}>点击按钮提示数据</button><br></br>
                </div>
            )
        }
    }
    

    打印 myRef

    React--10: 组件的三大核心属性3:refs与事件处理

    获得节点对应的值

    showData = ()=>{
            console.log(this.myRef.current.value)
        }
    

    但是这种容器,只能存一个。如果有多个节点,那只能声明多个myRef。


    起源地下载网 » React--10: 组件的三大核心属性3:refs与事件处理

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元