state的创建方法
类组件才是有状态的组件,如果是Arrow Function创建的组件,也叫做无状态组件(stateless compoment)
1.react里的第一种state定义
export default class App extends Component {
state = {
name: 'tianlanlan',
age: 18,
skills: [{
id: 1,
title: '吃饭'
}, {
id: 2,
title: '睡觉'
},{
id: 3,
title: '打豆豆'
}]
}
render() {
return (
<Fragment>
<dl>
<dt>名字</dt>
<dd>{this.state.name}</dd>
</dl>
<dl>
<dt>年龄</dt>
<dd>{this.state.age}</dd>
</dl>
<dl>
<dt>技能</dt>
{
// 这里是语句,循环输出,在react里就是直接用map。而不是for
// 而且这里不需要直接赋值,而是直接写map语句
// 在React的循环里,必须要有一个key
this.state.skills.map(item => {
return (
<dd key={item.id}>{item.title}</dd>
)
})
}
</dl>
</Fragment>
)
}
}
复制代码
constructor () {
super();
this.state = {
name: 'tianlanlan',
age: 18,
skills: [{
id: 1,
title: '吃饭'
}, {
id: 2,
title: '睡觉'
},{
id: 3,
title: '打豆豆'
}]
}
}
render() {
return (
<Fragment>
<dl>
<dt>名字</dt>
<dd>{this.state.name}</dd>
</dl>
<dl>
<dt>年龄</dt>
<dd>{this.state.age}</dd>
</dl>
<dl>
<dt>技能</dt>
{
// 这里是语句,循环输出,在react里就是直接用map。而不是for
// 而且这里不需要直接赋值,而是直接写map语句
// 在React的循环里,必须要有一个key
this.state.skills.map(item => {
return (
<dd key={item.id}>{item.title}</dd>
)
})
}
</dl>
</Fragment>
)
}
复制代码
state的主要目的是为了把一些需要改变的数据管理起来,方便后期用数据决定显示的思想来进行重新渲染
事件绑定
1.箭头函数
定义一个事件,把一个箭头函数赋值给一个变量,在调用的时候,就用this.handleAgeAdd来进行调用
(1) 在react里不能!不能!不能!直接修改state,这样只是值更改了,不会触发render()
handleAgeAdd = ()=> {
this.state.age++
console.log(this.state.age)
}
复制代码
注意:
React不允许直接修改state,需要调用setState的方法来进行修改,每一次的state修改会直接反映到UI界面上
(2)如果需要更新state,必须!必须!必须!调用setState方法
handleAgeAdd = ()=> {
this.setState({
// 这里不能用++
age: this.state.age + 1
})
console.log(this.state.age)
}
复制代码
2.不是箭头函数
(1)setState的第一个参数,可以是一个对象
handleAgeAdd () {
this.setState({
age: this.state.age + 1
}, () => {
// 如果要获取到最新的state,需要在setState的第二个回调函数里去获取
console.log('回调函数打印:', this.state.age)
})
// 这里永远打印出来的是上一次的state,而不是setState之后的,因为setState是异步的
console.log('外面打印:', this.state.age)
}
复制代码
如果要获取到最新的state,需要在setState的第二个回调函数里去获取
setState外面打印出来的是上一次的state,而不是setState之后的,因为setState是异步的
(2)setState的第一个参数,也可以是一个方法,但是,这个方法里必须要return一个对象
handleAgeAdd () {
// 这个方法里的第一个参数,特别有用,是上一次的state
this.setState((prevState) => {
console.log(prevState)
return {
age: prevState.age + 1
}
})
}
复制代码
注意:
// 如果是箭头函数,直接调用方法
<button onClick={this.handleAgeAdd}>增加一岁</button>
复制代码
// 如果不是箭头函数, 需要bind(this)
// 不推荐在render方法里bind(this),因为render方法会随着状态的更改,多次执行
<button onClick={this.handleAgeAdd.bind(this)}>增加一岁</button>
复制代码
// 如果不是箭头函数定义的方法,推荐在constructor这里进行bind(因为constructor只执行一次)
this.handleAgeAdd = this.handleAgeAdd.bind(this)
复制代码
补充:
1. input 中的 onchange 事件中有一个event对象
handleInputChange = (e) => {
console.log(e)
}
复制代码
<input
type="text"
onChange={this.handleInputChange}
/>
复制代码
handleInputChange = (e) => {
console.log(e.target)
}
复制代码
2.push的返回值
todos: this.state.todos.push(todo)
复制代码
注意:
这里的push要出错,因为push是更改了原来state里的值,但是返回的值又是一个长度,所以这样得到的todos就是一个数字,而不是一个数组
可以写成:
this.setState({
1.todos: this.state.todos.concat(todo)
2.todos: [...this.state.todos, todo]
3.todos: this.state.todos.slice().concat(todo)
})
// 深拷贝: 为了不破坏原有的值,我们需要深拷贝,JSON的方式做深拷贝,如果拷贝的内容中含有方法,则不可以拷贝
4.const todos = cloneDeep(this.state.todos)
todos.push(todo)
this.setState({
todos
})
5.const todos = JSON.parse(JSON.stringify(this.state.todos))
todos.push(todo)
this.setState({
todos
})
复制代码
3.createRef
// 要想使用ref, 需要引入createRef方法
import React, { Component, createRef } from 'react'
export default class Input extends Component {
constructor() {
super()
// 初始化一个ref
this.input = createRef();
}
handleAddClick = () => {
this.setState({
inputValue: ''
}, () => {
// 获取ref
console.log(this.input.current)
// 添加完成之后,自动获取焦点
this.input.current.focus()
})
}
render() {
return (
<div>
<input
type="text"
// 给input的ref赋值
ref={this.input}
value={this.state.inputValue}
onChange={this.handleInputChange}
/>
<button onClick={this.handleAddClick}>添加</button>
</div>
)
}
复制代码
聚焦之前
自动获取焦点