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>
)
}