1. State状态理解
关于state
的理解
state
是组件对象中最重要的属性,值是对象(可以包含多个数据)组件被称为"状态机",通过更新组件的state来更新对应的页面显示(重新渲染组件)
state
是组件实例的属性,函数组件没有实例,因为函数组件没有状态state
可以理解是组件自己的数据, props数据是外部传入,state数据就是组件自己的
2. State状态的使用
2.1 state使用规则
state 通常在组件的constructor中进行初始化
state 只能用setState方法更新
setState会导致render重新执行,渲染组件和所有的子组件
1) 初始化状态
constructor(props){
super(props)
// 定义state状态
this.state = {
flag: true,
firstMsg: "天王盖地虎",
lastMsg : "小鸡炖蘑菇"
}
}
2) 读取某个状态值
render(){
let flag = this.state.flag;
let firstMsg = this.state.firstMsg;
let lastMsg = this.state.lastMsg;
// 简写方式: 结构获取state中的数据
// let {flag,firstMsg, lastMsg} = this.state;
return (
{ flag ? firstMsg :lastMsg}
)
}
3) 更新状态 --> 组件界面更新
this.setState({
stateProp1: value1,
stateProp2: value2
})
2.2 示例代码:
class MyCom extends React.Component{
constructor(props){
super(props);
// 定义state状态
this.state = {
flag: true,
firstMsg: "天王盖地虎",
lastMsg : "小鸡炖蘑菇"
}
}
changeFlag = () => {
// 修改state状态数据
this.setState({
// 取出状态取反,然后改变状态
flag : !this.state.flag
})
}
render(){
// let flag = this.state.flag;
// let firstMsg = this.state.firstMsg;
// let lastMsg = this.state.lastMsg;
let {flag,firstMsg, lastMsg} = this.state;
return (
{ flag ? firstMsg :lastMsg}
)
}
}
ReactDOM.render( , document.getElementById("app"))
示例说明:
- setState每次修改内容会自动触发React重新渲染页面
- 因此示例中每次点击都会修改状态,更加状态重新渲染内容,达到内容切换的目的
2.3 状态的简写定义
2.3.1 说明:
- ES6 class类中 constructor 函数为构造函数, 内部通过this定义的属性是类实例的属性
- class类中其他的方法确实实例原型上的方法
- 但是class类中的表达式定义的内容确实实例上的内容
2.3.2 示例
class Person{
constructor(){
// 实例属性
this.name = "张三"
}
// 实例上的属性
age = 18
// 实例上的方法
eat = function(){
console.log("eat")
}
// 原型上的方法
run(){
console.log("eat")
}
}
var xm = new Person
console.log(xm)
/*
打印结果:
Person {age: 18, name: "张三", eat: ƒ}
age: 18
eat: ƒ ()
name: "张三"
__proto__:
constructor: class Person
run: ƒ run()
__proto__: Object
*/
示例说明:
- ES6中class类里定义的表达式,无论是函数表达式,函数普通的表达式,最后都是实例的属性或方法
- ES6中class类中普通定义的函数是实例原型上的方法
因此我们如果想简写state的定义,就可以如下定义:
示例代码:
class MyCom extends React.Component{
constructor(props){
super(props);
}
// 初始化定义state状态
state = {
flag: true,
firstMsg: "天王盖地虎",
lastMsg : "小鸡炖蘑菇"
}
// 组件实例化上的方法
changeFlag = () => {
// 修改state状态数据
this.setState({
// 取出状态取反,然后改变状态
flag : !this.state.flag
})
}
render(){
let {flag,firstMsg, lastMsg} = this.state;
return (
{ flag ? firstMsg :lastMsg}
)
}
}
ReactDOM.render( , document.getElementById("app"))
3. 关于函数组件
3.1 说明
- 不知道有没有人这么思考过, 函数组件没有状态
- 我们是否可以使用变量来模拟状态的概念呢
- 好像状态也就是一个数据, 定义的变量来存储数据是否可以
3.2 示例代码:
// 定义数据
let state = {
flag: true,
firstMsg: "天王盖地虎",
lastMsg : "小鸡炖蘑菇"
}
function MyCom(){
// 获取数据
let {flag,firstMsg, lastMsg} = state;
// 修改数据函数
let changeFlag = () => {
console.log(11);
// 11
state.flag = !state.flag
}
// 返回react元素
return (
{ flag ? firstMsg :lastMsg}
)
}
// 页面渲染
ReactDOM.render( , document.getElementById("app"))
示例说明:
- 当每次点击的时候,控制台会打印
11
说明事件没有任何问题 - 每次点击过后,在控制台打印
state
数据,会发现flag
的值发生了变化 - 可以页面却并没有任何变化
- 原因在于普通变量数据的变化并不会触发react重新渲染页面,但state会
- 如果真的希望页面重绘,就需要封装渲染函数,手动触发
3.3 封装渲染函数
修改示例代码如下:
function MyCom(){
let {flag,firstMsg, lastMsg} = state;
let changeFlag = () => {
console.log(11);
state.flag = !state.flag
// 每次flag值发生改变,重新渲染页面
render()
}
return (
{ flag ? firstMsg :lastMsg}
)
}
// 封装页面渲染函数
function render(){
ReactDOM.render( , document.getElementById("app"))
}
// 初始渲染一次
render()
示例说明:
- 将
React.render
渲染函数封装在render
函数中 - 每次修改数据完毕后,手动的调用
render
函数,重新渲染页面 - 因此大多数情况下回选择使用
state
状态