1. State狀態(tài)理解
關(guān)于state
的理解
state
是組件對(duì)象中最重要的屬性,值是對(duì)象(可以包含多個(gè)數(shù)據(jù))組件被稱為"狀態(tài)機(jī)",通過更新組件的state來更新對(duì)應(yīng)的頁面顯示(重新渲染組件)
state
是組件實(shí)例的屬性,函數(shù)組件沒有實(shí)例,因?yàn)楹瘮?shù)組件沒有狀態(tài)state
可以理解是組件自己的數(shù)據(jù), props數(shù)據(jù)是外部傳入,state數(shù)據(jù)就是組件自己的
2. State狀態(tài)的使用
2.1 state使用規(guī)則
state 通常在組件的constructor中進(jìn)行初始化
state 只能用setState方法更新
setState會(huì)導(dǎo)致render重新執(zhí)行,渲染組件和所有的子組件
1) 初始化狀態(tài)
constructor(props){
super(props)
// 定義state狀態(tài)
this.state = {
flag: true,
firstMsg: "天王蓋地虎",
lastMsg : "小雞燉蘑菇"
}
}
2) 讀取某個(gè)狀態(tài)值
render(){
let flag = this.state.flag;
let firstMsg = this.state.firstMsg;
let lastMsg = this.state.lastMsg;
// 簡寫方式: 結(jié)構(gòu)獲取state中的數(shù)據(jù)
// let {flag,firstMsg, lastMsg} = this.state;
return (
<div> { flag ? firstMsg :lastMsg}</div>
)
}
3) 更新狀態(tài) --> 組件界面更新
this.setState({
stateProp1: value1,
stateProp2: value2
})
2.2 示例代碼:
class MyCom extends React.Component{
constructor(props){
super(props);
// 定義state狀態(tài)
this.state = {
flag: true,
firstMsg: "天王蓋地虎",
lastMsg : "小雞燉蘑菇"
}
}
changeFlag = () => {
// 修改state狀態(tài)數(shù)據(jù)
this.setState({
// 取出狀態(tài)取反,然后改變狀態(tài)
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 (
<div onClick={ this.changeFlag }> { flag ? firstMsg :lastMsg}</div>
)
}
}
ReactDOM.render(<MyCom/>, document.getElementById("app"))
示例說明:
- setState每次修改內(nèi)容會(huì)自動(dòng)觸發(fā)React重新渲染頁面
- 因此示例中每次點(diǎn)擊都會(huì)修改狀態(tài),更加狀態(tài)重新渲染內(nèi)容,達(dá)到內(nèi)容切換的目的
2.3 狀態(tài)的簡寫定義
2.3.1 說明:
- ES6 class類中 constructor 函數(shù)為構(gòu)造函數(shù), 內(nèi)部通過this定義的屬性是類實(shí)例的屬性
- class類中其他的方法確實(shí)實(shí)例原型上的方法
- 但是class類中的表達(dá)式定義的內(nèi)容確實(shí)實(shí)例上的內(nèi)容
2.3.2 示例
class Person{
constructor(){
// 實(shí)例屬性
this.name = "張三"
}
// 實(shí)例上的屬性
age = 18
// 實(shí)例上的方法
eat = function(){
console.log("eat")
}
// 原型上的方法
run(){
console.log("eat")
}
}
var xm = new Person
console.log(xm)
/*
打印結(jié)果:
Person {age: 18, name: "張三", eat: ?}
age: 18
eat: ? ()
name: "張三"
__proto__:
constructor: class Person
run: ? run()
__proto__: Object
*/
示例說明:
- ES6中class類里定義的表達(dá)式,無論是函數(shù)表達(dá)式,函數(shù)普通的表達(dá)式,最后都是實(shí)例的屬性或方法
- ES6中class類中普通定義的函數(shù)是實(shí)例原型上的方法
因此我們?nèi)绻牒唽憇tate的定義,就可以如下定義:
示例代碼:
class MyCom extends React.Component{
constructor(props){
super(props);
}
// 初始化定義state狀態(tài)
state = {
flag: true,
firstMsg: "天王蓋地虎",
lastMsg : "小雞燉蘑菇"
}
// 組件實(shí)例化上的方法
changeFlag = () => {
// 修改state狀態(tài)數(shù)據(jù)
this.setState({
// 取出狀態(tài)取反,然后改變狀態(tài)
flag : !this.state.flag
})
}
render(){
let {flag,firstMsg, lastMsg} = this.state;
return (
<div onClick={ this.changeFlag }> { flag ? firstMsg :lastMsg}</div>
)
}
}
ReactDOM.render(<MyCom/>, document.getElementById("app"))
3. 關(guān)于函數(shù)組件
3.1 說明
- 不知道有沒有人這么思考過, 函數(shù)組件沒有狀態(tài)
- 我們是否可以使用變量來模擬狀態(tài)的概念呢
- 好像狀態(tài)也就是一個(gè)數(shù)據(jù), 定義的變量來存儲(chǔ)數(shù)據(jù)是否可以
3.2 示例代碼:
// 定義數(shù)據(jù)
let state = {
flag: true,
firstMsg: "天王蓋地虎",
lastMsg : "小雞燉蘑菇"
}
function MyCom(){
// 獲取數(shù)據(jù)
let {flag,firstMsg, lastMsg} = state;
// 修改數(shù)據(jù)函數(shù)
let changeFlag = () => {
console.log(11);
// 11
state.flag = !state.flag
}
// 返回react元素
return (
<div onClick={ changeFlag }> { flag ? firstMsg :lastMsg}</div>
)
}
// 頁面渲染
ReactDOM.render(<MyCom/>, document.getElementById("app"))
示例說明:
- 當(dāng)每次點(diǎn)擊的時(shí)候,控制臺(tái)會(huì)打印
11
說明事件沒有任何問題 - 每次點(diǎn)擊過后,在控制臺(tái)打印
state
數(shù)據(jù),會(huì)發(fā)現(xiàn)flag
的值發(fā)生了變化 - 可以頁面卻并沒有任何變化
- 原因在于普通變量數(shù)據(jù)的變化并不會(huì)觸發(fā)react重新渲染頁面,但state會(huì)
- 如果真的希望頁面重繪,就需要封裝渲染函數(shù),手動(dòng)觸發(fā)
3.3 封裝渲染函數(shù)
修改示例代碼如下:
function MyCom(){
let {flag,firstMsg, lastMsg} = state;
let changeFlag = () => {
console.log(11);
state.flag = !state.flag
// 每次flag值發(fā)生改變,重新渲染頁面
render()
}
return (
<div onClick={ changeFlag }> { flag ? firstMsg :lastMsg}</div>
)
}
// 封裝頁面渲染函數(shù)
function render(){
ReactDOM.render(<MyCom/>, document.getElementById("app"))
}
// 初始渲染一次
render()
示例說明:
- 將
React.render
渲染函數(shù)封裝在render
函數(shù)中 - 每次修改數(shù)據(jù)完畢后,手動(dòng)的調(diào)用
render
函數(shù),重新渲染頁面 - 因此大多數(shù)情況下回選擇使用
state
狀態(tài)