组件状态
在react hook出现之前,函数式组件是没有自己的状态的,所以我们统一通过类组件类讲解步骤:
初始化状态->读取状态->修改状态->影响视图
// 组件状态 类组件为演示
import React from "react"
class HelloTest extends React.Component {
// 定义组件状态
state = {
// 定义属性
name: 'seek0608',
age: 18
}
changeName = () => {
// 修改state中的状态name
// 注意:不可以直接复制修改,必须通过一个方法setState
//this.state.name = "test" ×
console.log(123)
this.setState({
name: 'demo'
})
}
render () {
return (
<div>
this is HelloTest
<div>
<h2>name: {this.state.name}</h2>
<button onClick={this.changeName}>修改name</button>
</div>
</div>
)
}
}
注意:
react编写组件就是编写原生js类或者函数、
定义状态必须通过state实例属性的方式提供一个对象,名称固定为state
修改state中 的任何属性,不能通过直接复制,必须走setState方法,这个方法来自于继承React.Component得到
this关键词很容易出现指向错误问题,请注意规范
this问题
由于this的指向问题,三种写法,但是实际中只需要写第一种即可
class Test extends React.Component {
// 定义组件状态
state = {
// 定义属性
counter: 1,
}
changeName = () => {
this.setState({
counter: this.state.counter + 1
})
}
render () {
return (
<div>
<button onClick={this.changeName}>{this.state.counter}click</button>
</div>
)
}
}
class Test2 extends React.Component {
// 定义组件状态
state = {
// 定义属性
counter: 1,
}
changeName () {
this.setState({
counter: this.state.counter + 1
})
}
render () {
return (
<div>
<button onClick={() => this.changeName()}>{this.state.counter}click</button>
</div>
)
}
}
class Test3 extends React.Component {
constructor() {
super()
this.changeName = this.changeName.bind(this)
}
// 定义组件状态
state = {
// 定义属性
counter: 1,
}
changeName () {
this.setState({
counter: this.state.counter + 1
})
}
render () {
return (
<div>
<button onClick={this.changeName}>{this.state.counter}click</button>
</div>
)
}
}
react的状态不可变
永远不要直接修改状态的值,而是基于当前状态创建新的状态值
import React from "react"
class Test extends React.Component {
state = {
counter: 1,
list: [1, 2, 4],
person: {
name: 'seek',
agw: 18
}
}
changeCounter = () => {
// 错误写法,是直接修改
this.state.counter++
++this.state.counter
this.state.counter += 1
// 正确写法
this.setState({
counter: this.state.counter + 1
})
}
changeList = () => {
// 错误写法,是直接修改
this.state.list.push(3)
this.state.list.pop()
// 正确写法
this.setState({
list: [...this.state.list, 3]
})
}
changePopList = () => {
this.setState({
list: this.state.list.filter(item => item !== 2)
})
}
changePerson = () => {
// 错误写法,是直接修改
this.state.person.name = "seek0608"
this.setState({
person: {
...this.state.person,
name: 'rose'
}
})
}
render () {
return (
<>
<div>{this.state.counter}</div>
<ul>
{this.state.list.map(item => <li key={item}>{item}</li>)}
</ul>
<div>{this.state.person.name}</div>
<button onClick={this.changeCounter}>{this.state.counter}click</button>
<button onClick={this.changeList}>{this.state.counter}click</button>
<button onClick={this.changePopList}>{this.state.counter}click</button>
<button onClick={this.changePerson}>{this.state.counter}click</button>
</>
)
}
}
function App () {
return (
<div className="App">
<Test />
</div>
)
}
export default App
表单处理——受控组件
例如:input框自己状态被react组件的状态控制
react组件的状态的地方是在state中,input表单元素也有自己的状态是在value中,react将state与表单元素的值绑定在一起,由state的值来控制表单元素的值,从而保证单一数据源特性
实现步骤:
- 在组件的state中声明一个组件的状态数据
- 将状态数据设置为input标签元素的value属性的值
- 为input添加change事件,在事件处理程序中,通过事件对象e获取到当前文本框的值(
即用户当前输入的值
) - 调用setState方法,将文本框的值作为state状态的最新值
class Counter extends React.Component {
state = {
counter: 'this is message',
}
changeCounter = (e) => {
this.setState({
counter: e.target.value
})
}
render () {
return (
<>
<div>{this.state.counter}</div>
<input type='text' value={this.state.counter} onChange={this.changeCounter} />
</>
)
}
}
表单处理——非受控组件
非受控组件就是通过手动操作dom的方式获取文本框的值,文本框的状态不受react组件的state中的状态控制,直接通过原生dom获取输入框的值
实现步骤
- 导入
createRef
函数 - 调用createRef函数,创建一个ref对象,存储到名为
msgRef
的实例属性中 - 为input添加ref属性,值为
msgRef
- 在按钮的事件处理程序中,通过
msgRef.current
即可拿到input对应的dom元素,而其中msgRef.current.value
拿到的就是文本框的值
import React, { createRef } from "react"
class InputComponent extends React.Component {
// 这个实例属性是可以自定义的,语义化即可
msgRef = createRef()
state = {
value: ""
}
getInputValue = () => {
this.setState({
value: this.msgRef.current.value
})
}
// UI结构
render () {
return (
<>
<input type='text' ref={this.msgRef} />
<h1>{this.state.value}</h1>
<button onClick={this.getInputValue}>点击获取输入框的值</button>
</>
)
}
}
使用ref获取绑定,并通过如下方式获取value
this.msgRef.current.value
this.msgRef.current表示原生的dom元素,然后通过value获取