react表单和绑定事件及state和props-04

一、绑定事件

1、绑定事件处理函数this获取数据的几种方法:

第一种方式:在事件上使用bind(this)

<button onClick={this.getData1.bind(this)}>获取数据方法1</button>

第二种方式:在构造函数中改变this指向

this.getData2=this.getData2.bind(this)
<button onClick={this.getData2}>获取数据方法2</button>

第三种方式:使用=()=>

getData3=()=>{
    alert(this.state.dataMsg)
}
<button onClick={this.getData3}>获取数据方法3</button>

关于React中this指向问题

JavaScript函数中的this不是在函数声明的时候定义的,而是在函数调用(即运行)的时候定义的。在react中也遵循这个原则,this指向该function的调用方,所以“调用者”不同会导致this的不同,这里的“调用者”指的是函数执行时的当前对象。

箭头函数或是bind会改变this的指向。上面的this.state,之所以能够访问到state就是改变了this的指向,不然getData里的this就是指向这个function,这是的this是undefined。

一般来说:
    1、谁调用的this就指向谁。
    2、箭头函数,bind改变后的指向父层。

2、对state中的数据进行赋值

在react中我们使用setState来更新数据:

dataMsg:'原数据'
setData=()=>{
    //此处使用setState来更新数据
    this.setState({
        dataMsg:'数据已被改变'
    })
    console.log(this.state.dataMsg)
}

但是console打印出来的值是:原数据。
这里就要提到react里setState的异步了,在react里setState这个方法是异步的,不会按顺序执行,它可能会等待一组state一起进行更新,来提高性能。下面提供一个解决办法,setState的回调setState(updater[, callback]),相当于componentDidUpdate函数:

setData=()=>{
    //此处使用setState来更新数据
    //setState的回调setState(update, ()=>{//更新完后执行的代码}),
    this.setState({
        dataMsg:'数据已被改变'
    },()=>{
        console.log(this.state.dataMsg)
    }
}
3、方法的传值

因为在事件中使用onClick={this.setData()}时方法直接执行,直接写成this.setData(data)这样会报错,所以需要使用bind():

//看参数,第一个参数需要是this或是一个函数
//第二个参数为需要传递参数
bind(this: Function, thisArg: any, ...argArray: any[]): any)

下面看如何传递:

<button className="myFormEvent-setData2-btn" onClick={this.setData.bind(this,["第一个参数","第二个参数","第三个参数"])}>执行方法传值2</button>
//多个参数时str即为数组
setData=(str)=>{
  this.state({
    msg:str[0],
    dataMsg:str[2]
  })
}

二、事件对象

事件对象:在出发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事件有关的信息。

1、使用event.target获取相关属性值:
event.target.style.background //获取或更改背景色
event.target.getAttribute("aid") //获取自定义属性的值
event.target.setAttribute("aid","aaa")//设置自定义属性的值
e.target.value //获取输入框的值
//按钮点击事件
<button aid="aaa" onClick={this.getEvent}></button>
getEvent=(event)=>{
    //使用event.target来改变颜色
    event.target.style.background="red";
    //使用event.target.getAttribute("aid")里获取button的自定义属性aid的值
    //使用event.target.setAttribute("aid","aaa")来设置button的自定义属性aid的值
    console.log(event.target.getAttribute("aid"));
}
//输入框改变事件
<input onChange={this.inputChange}></input>
inputChange=(e)=>{
    //使用event.target.value获取表单输入值
    console.log(e.target.value);
}
2、使用this.refs来获取值

给标签添加ref属性,在事件里通过this.refs.[属性].value来获取值

<input ref="val" onChange={this.refChange}/><button onClick={this.getRefVal}>通过ref获取输入框的值</button>
refChange=()=>{
    //获取值
    let str = this.refs.val.value;
    this.setState({
        val:str
    })
}
3、event的部分事件
输入框事件:
  onChange:输入框改变时触发
键盘事件:
  onKeyUp:按键抬起时触发
  onKeyDown:按键按下时触发
点击事件:
  onClick:点击时触发

三、react的表单

1、双向数据绑定

双向数据绑定在vue中有,在react中是没有的,双向数据绑定就是双方的数据改变相互影响,下面只是模拟双向数据绑定:

//输入框使用value时需要添加onChange监听事件
//还可以使用defaultValue
<input value={this.state.data} onChange={this.inputDataChange} /><button onClick={this.getInputData}>改变model数据为data</button><br/>
数据显示:{this.state.data}<br/>

//初始化
constructor(props){
    super(props);
    this.state={
        data:'data'
    }
}
//输入框值改变时改变state的值,视图上相对改变
inputDataChange=(e)=>{
    //此处是输入框状态改变的数据
    this.setState({
        data:e.target.value
    })
}
//相当于state的值改变,视图上的值也改变
getInputData=()=>{
    //此处是点击时要改变的数据
    this.setState({
        data:'data'
    })
}

上面的的value需要事件监听,这里面有一个react的知识点:约束性组件和非约束性组件
约束性组件,简单说就是react管理了它的value,而非约束性组件的value是由原生DOM管理的。

约束性组件是这样写的:

<input value={this.state.data} onChange={this.inputDataChange} />

这里的value属性不再是一个写死的值,它是this.state.data,而this.state.data是由this.inputDataChange这个监听事件负责管理的。
这个时候实际上 input 的 value 根本不是用户输入的内容。而是onChange 事件触发之后,由 this.setState 导致了一次重新渲染。不过React会优化这个渲染过程,实际它依然是通过设置input的value来实现的。

非约束性组件是这样写的:

<input defaultValue="a" />

这个defaultValue就是原生DOM中的value属性,其value值就是用户输入的内容,react不管理输入的过程。

对比约束性组件和非约束性组件的输入流程:
*约束性组件: 用户输入A -> 触发onChange事件 -> inputDataChange 中设置 state.name = “A” -> 渲染input使他的value变成A
*非约束性组件: 用户输入A -> input 中显示A

2、react表单的写法

这里介绍form表单里的几种常用的子标签:
一般表单都是需要用form标签包起来:

<form></form>
  • 阻止表单的默认提交
    有时我们需要阻止表单的默认提交,来自己把握什么时候提交调用preventDefault()方法,如下:
<form onSubmit={this.doSubmit}></form>
doSubmit=(e)=>{
    //使用事件e来调 preventDefault()方法来阻止表单默认提交
    e.preventDefault();
}
  • 文本框
    设置value属性,因为是约束性组件,所以需要onChange触发事件,下面的都是这样
    在事件方法handleName(event)里使用event.target.value来获取输入框中的值,如下:
constructou(props){
    super(props);
    this.state={
        name:''
    }
}
handleName=(e)=>{
    this.setState({
        name:e.target.value
    })
}

姓名:<input type="text" value={this.state.name} onChange={this.handleName}  />
  • 单选框
    单选框非手动输入,所以需要在标签上加入value属性,否则获取不到数据。因为我们要选择,所以要添加checked,来判断选中状态:
constructou(props){
    super(props);
    this.state={
       //默认选中女
        sex:'0'
    }
}
/**
    checked={this.state.sex==0}是判断是否为选中状态
    当点击选中按钮后获取当前选中的value值,然后改变sex的值
    react重新渲染后,点击的按钮变为被选中状态
*/
handleSex=(e)=>{
    this.setState({
        sex:e.target.value
    })
}

性别:<input type="radio" checked={this.state.sex==0} value="0" onChange={this.handleSex} />男
      <input type="radio" checked={this.state.sex==1} value="1" onChange={this.handleSex} />女
  • 下拉框
    下拉框里的数据是数组,所以我们需要用到循环获取,我们需要有个变量city来存储选中的值,看代码:
constructou(props){
    super(props);
    this.state={
        city:'',
        citys:[
             '北京','上海','深圳'
        ]
    }
}
handleCity=(e)=>{
    this.setState({
        city:e.target.value
    })
}

/**
    使用map()来循环数据,注意map(function(value,key){})
    的this的指向,此时的this是无法调用state的
    注意:return中是需要一个根标签包裹的,此处<option>即可
    需要在option上添加key,map循环需要,以便更好的管理数据
*/
城市:
<select value={this.state.city} onChange={this.handleCity}>
    {this.state.citys.map(function(value,key){
        return(
            <option key={key} >{value}</option>
        )
    })}
</select>
  • 复选框
constructou(props){
    super(props);
    this.state={
        hobby:[
            {'title':'睡觉','checked':true},
            {'title':'吃饭','checked':false},
            {'title':'听音乐','checked':false}
        ]
    }
}
/**
    hobby是个数组,我们通过key来找到选中状态,当点击时通过
    hobby[key].checked = !hobby[key].checked;
    来改变选中状态,然后将hobby重新赋值,和单选框类似
*/
handleHobby(key){
    var hobby = this.state.hobby;
    hobby[key].checked = !hobby[key].checked;
    this.setState({
        hobby:hobby
    })
}

/**
    因为我们需要key来找到选项的选中状态,所以我们需要把key传到方法中,
    此处使用箭头函数将map函数中的this指向调整了,所以在return中可以是用this.handleHobby
*/
喜好:
{this.state.hobby.map((value,key)=>{
    return(
        <span key={key}>
            <input type="checkbox" checked={value.checked} onChange={this.handleHobby.bind(this,key)}/>{value.title}
        </span>
    )
})}
  • 文本域
    和文本框类似:
constructou(props){
    super(props);
    this.state={
        info:''
    }
}
handleInfo=(e)=>{
    this.setState({
        info:e.target.value
    })
}

info:<input  type="textarea" value={this.state.info} onChange={this.handleInfo}/>

四、react中的state和props

props

1、react的组件从概念上看就是一个函数,可以接受一个参数最为输入值,这个参数就是props,可以把props理解为从外部传入组件内部的数据。
2、props经常被用作渲染组件和初始化状态,当一个组件被实例化之后,它的props是只读的,不可改变的。如果props在渲染过程中可以被改变,会导致这个组件显示的形态变得不可预测。只有通过父组件重新渲染的方式才可以把新的props传入组件中。
3、在组件中,我们最好为props中的参数设置一个defaultProps,并且制定它的类型。

state

一个组件的显示形态可以由数据状态和外部参数所决定,外部参数也就是props,而数据状态就是state
state的主要作用是用于组件保存、控制以及修改自己的状态,它只能在constructor中初始化,它算是组件的私有属性,不可通过外部访问和修改,只能通过组件内部的this.setState来修改,修改state属性会导致组件的重新渲染。


写在最后:

  • 如果文章中有错误或是表达不准确的地方,欢迎大家评论中指正,以便我完善。
  • 文章我也会根据所学到新的知识不断更新。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352