React组件 (三)

组件实例的三大属性 3 : refs

(1)ref用于标识组件内部某个元素(组件内的标签可以定义ref属性来标识自己)

(2)refs 是标识集合

字符串形式的refs

<input ref="input1"/>

例子


class Demo extends React.Component{ 
    getData = () => {
        console.log(this.refs.input1.value); 
    }

    getData1 = () => {
        console.log(this.refs.input2.value); 
    } 
    render(){
        return (
            <div>
                <input type="text" placeholder="点击按钮提示数据" ref="input1"/> 
                <button onClick={this.getData} ref="button">点击按钮</button>
                <input type="text" placeholder="失去焦点提示数据" ref="input2" onBlur={this.getData1}/> 
            </div>
        )
    }
}
ReactDOM.render(<Demo />,document.getElementById("test"))

回调形式的refs

<input ref={(c)=>{this.input1 = c}}/>

例子


class Demo extends React.Component{ 
    getData = () => {
        console.log(this.input1.value); 
    } 
    getData1 = () => {
        console.log(this.input2.value); 
    } 
    render(){
        return (
            <div>
                <input type="text" placeholder="点击按钮提示数据" ref={(currentNode) => {this.input1 = currentNode,console.log("3333")}}/> 
                <button onClick={this.getData} ref="button">点击按钮</button>
                <input type="text" placeholder="失去焦点提示数据" ref={c => this.input2 = c} onBlur={this.getData1}/> 
            </div>
        )
    }
}
ReactDOM.render(<Demo />,document.getElementById("test"))

回调ref中调用次数的问题

关于回调 refs 的说明

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


class Demo extends React.Component{  
state = {
  isHot:true
} 
getData = () => {
  console.log(this.input1.value); 
} 
changeWether = () => {
  this.setState({
      isHot:!this.state.isHot
  })
} 
render(){
  const {isHot} = this.state 
  return (
      <div>
          <h1>今天天气{isHot ? '炎热':'凉爽'}</h1>
          <input type="text" placeholder="点击按钮提示数据" ref={(currentNode) => {this.input1 = currentNode,console.log("@1222",currentNode)}}/> 
          <button onClick={this.getData} ref="button">点击按钮</button>
          <button onClick={this.changeWether}>点击切换天气</button>
      </div>
  )
}
}
ReactDOM.render(<Demo />,document.getElementById("test"))

react提供的解决办法


saveInput = (currentNode) => {
    this.input1 = currentNode;
    console.log("@1222",currentNode)
}

<input type="text" ref={this.saveInput}/>

createRef创建ref容器


myRef = React.createRef() 
<input ref={this.myRef}/>

例子


class Demo extends React.Component{  
    /**
     * React.createRef 调用后可以返回一个容器,该容器可以存储被ref所标识的节点
     * 该容器是“专人专用的”
     */ 
    myRef = React.createRef(); 
    myRef2 = React.createRef(); 
    getData = () => {
        console.log(this.myRef.current.value); 
    } 
    getData1 = () => {
        console.log(this.myRef2.current.value); 
    } 
    render(){
        return (
            <div>
                <input type="text" placeholder="点击按钮提示数据" ref={this.myRef}/> 
                <button onClick={this.getData} ref="button">点击按钮</button>
                <input type="text" placeholder="失去焦点提示数据" ref={this.myRef2} onBlur={this.getData1}/> 
            </div>
        )
    }
}
ReactDOM.render(<Demo />,document.getElementById("test"))

事件处理

1)通过onXxx属性指定事件处理函数(注意大小写)

a.React使用的是自定义(合成)事件, 而不是使用的原生DOM事件 ————为了更好的兼容性

b.React中的事件是通过事件委托方式处理的(委托给组件最外层的元素) ———— 为了高效

2)通过event.target得到发生事件的DOM元素对象 ———— 勿过度使用 Refs


class Demo extends React.Component{   
   myRef = React.createRef(); 
   myRef2 = React.createRef(); 
   getData = () => {
       console.log(this.myRef.current.value); 
   } 
   getData1 = () => {
       console.log(event.target.value);  // 通过event.target得到发生事件的DOM元素对象
   } 
   render(){
       return (
           <div>
               <input type="text" placeholder="点击按钮提示数据" ref={this.myRef}/> 
               <button onClick={this.getData} ref="button">点击按钮</button>
               <input type="text" placeholder="失去焦点提示数据" ref={this.myRef2} onBlur={this.getData1}/> 
           </div>
       )
   }
}
ReactDOM.render(<Demo />,document.getElementById("test"))

收集表单数据

需求

定义一个包含表单的组件

输入用户名密码后, 点击登录提示输入信息

非受控组件

表单数据由DOM本身处理。即不受setState()的控制,与传统的HTML表单输入相似,input输入值即显示最新值(使用 ref从DOM获取表单值)


class LoginForm extends React.Component{   
    myRef = React.createRef(); 
    myRef2 = React.createRef(); 
    getData = (event) => {
        event.preventDefault(); // 阻止表单提交
        console.log(`用户名是:${this.myRef.current.value};密码是:${this.myRef2.current.value}`); 
    } 
     
    render(){
        return (
            <form onSubmit={this.getData}>
                用户名是:<input type="text" placeholder="请输入用户名" ref={this.myRef} name="username"/><br/>
                密码:<input type="password" placeholder="请输入密码" ref={this.myRef2} name="password"/><br/>
                <button>登录</button> 
            </form>
        )
    }
}
ReactDOM.render(<LoginForm />,document.getElementById("test"))

受控组件

在HTML中,标签<input><textarea><select>的值的改变通常是根据用户输入进行更新。在React中,可变状态通常保存在组件的状态属性中,并且只能使用 setState() 更新,而呈现表单的React组件也控制着在后续用户输入时该表单中发生的情况,以这种由React控制的输入表单元素而改变其值的方式,称为:“受控组件”。

class LoginForm extends React.Component{  
    state = {
        username:"",
        password:""
    }

    getData = (event) => {
        event.preventDefault(); // 阻止表单提交
        console.log(`用户名是:${this.state.username};密码是:${this.state.password}`); 
    } 

    
    getUserName = (event) => {
        this.setState({
            username:event.target.value
        })
    }

    getPassword = (event) => {
        this.setState({
            password:event.target.value
        })
    }
     
    render(){
        return (
            <form onSubmit={this.getData}>
                用户名是:<input type="text" placeholder="请输入用户名" name="username" onChange={this.getUserName}/><br/>
                密码:<input type="password" placeholder="请输入密码" name="password" onChange={this.getPassword}/><br/>
                <button>登录</button> 
            </form>
        )
    }
}
ReactDOM.render(<LoginForm />,document.getElementById("test"))

高阶函数-柯里化

高阶函数:如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数。

  • 1.若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数。

  • 2.若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数。

  • 常见的高阶函数有:Promise、setTimeout、arr.map()等等

函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式。


function sum(a){
  return(b)=>{
    return (c)=>{
      return a+b+c
    }
  }
}



class LoginForm extends React.Component{  
  state = {
      username:"",
      password:""
  }

  getData = (event) => {
      event.preventDefault(); // 阻止表单提交
      console.log(`用户名是:${this.state.username};密码是:${this.state.password}`); 
  }  
 
  saveFormData = (dataType) => { 
      return (event) => {
          this.setState({
              [dataType]:event.target.value
          })
      }
  }
   
  render(){
      return (
          <form onSubmit={this.getData}>
              用户名是:<input type="text" placeholder="请输入用户名" name="username" onChange={this.saveFormData('username')}/><br/>
              密码:<input type="password" placeholder="请输入密码" name="password" onChange={this.saveFormData('password')}/><br/>
              <button>登录</button> 
          </form>
      )
  }
}
ReactDOM.render(<LoginForm />,document.getElementById("test"))  

不用柯里化的写法


saveFormData = (dataType,event) => {  
    this.setState({
        [dataType]:event.target.value
    })
    
}
 
render(){
    return (
        <form onSubmit={this.getData}>
            用户名是:<input type="text" placeholder="请输入用户名" name="username" onChange={(event) => {this.saveFormData('username',event)}}/><br/>
            密码:<input type="password" placeholder="请输入密码" name="password" onChange={(event) => {this.saveFormData('password',event)}}/><br/>
            <button>登录</button> 
        </form>
    )
}
posted @ 2021-03-09 10:13  流年瓦解我们的记忆  阅读(76)  评论(0编辑  收藏  举报