事件绑定中的this指向
- 1、箭头函数
利用箭头函数自身不绑定this的特点
render()方法中的this为组件实例,可以获取到setState()
render(){
//箭头函数的this并不属于箭头函数自身,指向外部环境render()方法,render()的this指向当前实例
return (
<div>
<h1>计数器:{this.state.count}</h1>
<button onClick = {()=>{this.onIncrement()}}>增加</button>
</div>
)}
- 2、Function.prototype.bind()
利用ES5的bind方法,将事件处理程序中的this与组件实例绑定到一起
bind()方法创建一个新的函数,在bind被调用时,这个新函数的this被指定为bind()的第一个参数
constructor(){
super()
//初始化state
this.state = {
count:0
}
this.onIncrement = this.onIncrement.bind(this)
}
<h1>计数器:{this.state.count}</h1>
<button onClick = {this.onIncrement}>增加</button>
先调用construtor函数,再调用render函数,render函数里的this.onIncrement是被赋值之后的函数
3、class的实例方法—(推荐使用)
利用箭头函数形式的class实例方法
注意:该语法是实验性语法,脚手架中配置了babel,可以直接使用。
//事件处理程序
handleClick=()=>{
alert('事件已经触发!!')
}
onIncrement=()=>{
this.setState({
count: this.state.count+1
})
}
表单处理
受控组件
- HTML的表单元素是可输入的,也就是有自己的可变状态
- React中可变状态通常保存在state中,并且只能通过setState()方法来进行修改
- React将state与表单元素值value值绑定在一起,由state值控制表单元素的值
- 受控组件:值受到React控制的表单元素
state = {txt:''}
<input type = "text" value = {this.state.txt} onChange = {this.handleChange}/>
步骤
1、在state中添加一个状态,作为表单元素的value值
2、给表单元素绑定change事件,将表单元素的值设置为state的值(控制表单元素值的变化)
文本框、富文本框,下拉框,复选框的使用示例
文本框、富文本框、下拉框操作value属性
复选框操作checked属性
import React, { Component } from 'react'
export default class Control extends Component {
state = {
txt:'',
content:'',
city:'',
isChecked:false
}
handleChange = e=>{
this.setState({
txt:e.target.value
})
}
handleContent = e=>{
this.setState({
content:e.target.value
})
}
handleCity = e=>{
this.setState({
city:e.target.value
})
}
handleChecked = e =>{
this.setState({
isChecked:e.target.checked
})
}
render() {
return (
<div>
{/* 文本框 */}
<input type = "text" value = {this.state.txt} onChange = {this.handleChange}/>
<h1>{this.state.txt}</h1>
<br />
{/* 富文本框 */}
<textarea value = {this.state.content} onChange = {this.handleContent}></textarea>
<h1>{this.state.content}</h1>
<br />
{/* 下拉框 */}
<select value = {this.state.city} onChange = {this.handleCity}>
<option value = "sh">上海</option>
<option value = "bj">北京</option>
<option value = "gz">广州</option>
</select>
<h1>{this.state.city}</h1>
{/* 复选框 */}
<input type = "checkbox" checked = {this.state.isChecked} onChange = {this.handleChecked}/>
<h1> {this.state.isChecked}</h1>
</div>
)
}
}
多表单元素优化
问题:每个表单元素都有独立的事件处理程序,太繁琐
优化:使用一个事件处理程序同时处理多个表单元素
优化步骤
- 给表单元素添加name属性,名称与state相同,用于区分其他的表单元素,更新状态
- 根据表单元素类型获取对应的值,value/checked属性
const value = target.type===‘checkbox’ ? target.checked : target.value - 在change事件事件处理程序中[name]修改对应的state
const name = target.name this.setState({[name] : value})
import React, { Component } from 'react'
export default class ControlMajor extends Component {
state = {
txt:'',
content:'',
city:'',
isChecked:false
}
handleForm = e=>{
//获取当前DOM对象
const target = e.target
//根据类型获取值
const value = target.type==='checkbox' ? target.checked : target.value
//获取name
const name = target.name
this.setState({
[name] : value
})
}
render() {
return (
<div>
{/* 文本框 */}
<input type = "text" name = 'txt' value = {this.state.txt} onChange = {this.handleForm}/>
<h1>{this.state.txt}</h1>
<br />
{/* 富文本框 */}
<textarea name = 'content' value = {this.state.content} onChange = {this.handleForm}></textarea>
<h1>{this.state.content}</h1>
<br />
{/* 下拉框 */}
<select name = 'city' value = {this.state.city} onChange = {this.handleForm}>
<option value = "sh">上海</option>
<option value = "bj">北京</option>
<option value = "gz">广州</option>
</select>
<h1>{this.state.city}</h1>
{/* 复选框 */}
<input type = "checkbox" name = 'isChecked' checked = {this.state.isChecked} onChange = {this.handleForm}/>
<h1> {this.state.isChecked}</h1>
</div>
)
}
}
非受控组件(不推荐)
1、调用React.createRef()创建一个ref对象
2、将创建好的ref对象添加到文本框中
3、同股票ref对象获取文本框的值
React基础总结
- 组件的两种创建方式:函数组件与类组件
- 无状态(函数)组件,负责静态结构展示
- 有状态组件,负责更新UI,让页面动起来
- 绑定事件注意this指向问题
- 推荐使用受控组件处理表单
- 完全利用JS的语言特性创建组件,这是React的思想
完成小练习,写了一个组件
渲染评论列表(列表渲染)
没有评论时渲染:暂无评论(条件渲染),
获取评论信息(受控组件)
发表评论,更新评论列表(setState())
实现表单列表渲染,条件渲染,受控组件,,边界判断
import React, { Component } from 'react'
import '../CSS/test1.css'
export default class Test1 extends Component {
state = {
//初始化状态
comments: [
{ id: 1, name: 'jack', content: '沙发!!' },
{ id: 2, name: 'rose', content: '板凳!!' },
{ id: 3, name: 'tom', content: '楼主好人' }
],
userName:'',//评论人
userContent:''//评论信息
}
//渲染评论列表
renderList(){
return this.state.comments.length === 0 ?
(
<div className="no-content">暂无评论,快去评论吧~</div>
) :
(
<ul>
{this.state.comments.map(item =>
<li key={item.id}>
<h3>{item.name}</h3>
<p>{item.content}</p>
</li>
)}
</ul>
)
}
handleName = e=>{
this.setState({
userName:e.target.value
})
}
handleContent = e=>{
this.setState({
userContent:e.target.value
})
}
addContent = ()=>{
const {comments,userName,userContent} = this.state
//非空校验
if(userName.trim()===''||userContent.trim()===''){
alert("请输入评论人与评论信息")
return
}
const newComments = [{
id:Math.random(),
name:userName,
content:userContent
},...comments]
console.log(newComments)
this.setState ({
comments:newComments,
//清空文本框
userName:'',
userContent:''
})
}
render() {
return (
<div className="app">
<div>
<input className="user" type="text" placeholder="请输入评论人" value = {this.state.userName} onChange = {this.handleName}/>
<br />
<textarea
className="content"
cols="30"
rows="10"
placeholder="请输入评论内容"
value = {this.state.userContent}
onChange = {this.handleContent}
/>
<br />
<button onClick = {this.addContent}>发表评论</button>
</div>
{/* 条件渲染,通过数据长度判断 */}
{this.renderList()}
{/* {this.state.comments.length === 0 ?
(
<div className="no-content">暂无评论,快去评论吧~</div>
) :
(
<ul>
{this.state.comments.map(item =>
<li key={item.id}>
<h3>{item.name}</h3>
<p>{item.content}</p>
</li>
)}
</ul>
)
} */}
</div>
)
}
}
.app{
border: 1px solid;
width: 300px;
padding: 10px;
background-color: cyan;
}
.user{
width: 240px;
margin-top: 10px;
}
.content{
margin-top: 10px;
margin-bottom: 10px;
}
.no-content{
margin-top: 10px;
}