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>
)
}
}
複製程式碼
2.react裡的第二種state定義(大多使用第二種)constructor只執行一次
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>
)
}
複製程式碼
聚焦之前
自動獲取焦點