首先 咱們用最通俗易懂的話來理解, 好比 每一個人都有本身的狀態 , 每一個人的狀態 都會影響 他的行爲,react
那麼, 咱們將這句話放到 react 中去理解,把人看做是 組件,組件也有本身的狀態,組件的狀態會影響api
它的頁面。markdown
咱們在遊覽各大網頁時,會發現 網頁上有一些數據,如我的信息 帳號 以及一些新聞列表等等。 這些都app
是數據, 咱們將這些數據放在了頁面上,那麼是什麼驅動着頁面的改變呢? 是數據。 這時候咱們只須要函數
將數據 放入狀態 ( state ) 中 ,咱們去更改狀態 頁面也會隨之變化。this
import React, { Component } from 'react'
export default class App extends Component {
render() {
console.log(this)
return (
<div>
app組件
</div>
)
}
}
複製代碼
如今咱們回到 第一個問題 理解什麼是 state ?spa
1 . state 是組件對象最重要的屬性 ,值是對象 ( 裏面能夠包含多個 key : value 的 組合 ) 雖然在初始化看到的是null , 在react以前的版本中 仍是一個 { }3d
2 . 組件被稱之爲狀態機 , 經過更新組件裏的 state 來更新對應的頁面顯示 ( 從新渲染組件 )code
須要注意的地方 : 因有函數時組件與類式組件 react 將狀態放到了 實例對象裏 函數時組件 連this都沒有 哪兒來的 狀態呢? 在考慮初學者未接觸到 hooksorm
咱們 先從 類 組件來講。
import React, { Component } from 'react'
export default class App extends Component {
constructor(props) {
super(props)
// 初始化狀態
this.state = {
isHot: true
}
}
render() {
console.log(this)
return (
<div>123</div>
)
}
}
複製代碼
咱們在 類 中 放了一個 構造器 constructor , 調用了 super ( 傳遞的props 不在本章見作詳細說明 咱們先寫上 )
能夠看見 咱們初始化好了 一個 狀態 key : isHot value:true
render() {
console.log(this.state)
return (
<h2>今每天氣很{this.state.isHot ? '炎熱' : '寒冷'}</h2>
)
}
複製代碼
打開頁面與控制檯 咱們查看一下
須要注意的是 原生js 中的 onclick , onblur ... 等等 在 React 中 所有改成 onClick onBlur 這種小駝峯的寫法
import React, { Component } from 'react'
export default class App extends Component {
constructor(props) {
super(props)
this.state = {
isHot: true
}
}
render() {
return (
<h2 onClick={ clickTitle() }>今每天氣很{this.state.isHot ? '炎熱' : '寒冷'}</h2>
)
}
}
function clickTitle() {
console.log('標題被點擊了');
}
複製代碼
咱們能夠思考一下爲何 ?
onClick = { clickTitle() } 同等於 onClick = { 函數調用的返回值 }
咱們將返回值 直接給到了 onClick 他就自動的去給你點了
咱們將 onClick = { clickTitle() } 後面的調用給去掉 改成 onClick = { clickTitle }
從新回到頁面 咱們能夠看到 已經能夠進行正常的點擊操做了
此處 咱們接着上一個小節中的內容 繼續 。
我須要 點擊標題的時候 讓炎熱變成寒冷 這個時候怎麼去處理? 咱們須要將代碼修改爲 以下:
import React, { Component } from 'react'
export default class App extends Component {
constructor(props) {
super(props)
this.state = {
isHot: true
}
}
clickTitle() {
console.log('標題被點擊了');
}
render() {
return (
<h2 onClick={ this.clickTitle }>今每天氣很{this.state.isHot ? '炎熱' : '寒冷'}</h2>
)
}
}
複製代碼
首先 咱們只須要將 函數從實例的外面 放到實例的裏面去
那麼 clickTitle 這個方法放在哪兒了呢?
他放在了類的實例對象上,供實例使用
因此 咱們須要在
<h2 onClick={ this.clickTitle }>今每天氣很{this.state.isHot ? '炎熱' : '寒冷'}</h2>
複製代碼
這句話中 改爲 this.clickTitle
啓動項目 發現 標題依然是能夠被點擊的
接下來 咱們將函數內的代碼改成
clickTitle() {
console.log(this.state.isHot);
}
複製代碼
這時 控制檯就直接報錯了
咱們再去打印 this 時會發現 this 是 undefined
咱們能夠知道 constructor 和 render 中的 this 都是指組件的實例對象 ,那麼本身定義的clickTitle 裏的this爲何是undefined呢
首先咱們要了解到 只有當 clickTitle 這個方法 是組件的實例對象去調用的時候 它裏面的 this 纔是clickTitle的實例對象
constructor 裏的 this 必定是當前實例的 實例對象 是一個固定的東西
注意: 咱們須要知道的是 clickTitle 在調用的時候 並非App這個實例對象去調用他的
這時候 再思考一個問題 既然不是 這個實例去調用他的 那 this 爲何是 undefined 不是 window呢 ?
注意:在類中 所定義的方法 它會自動的去在你所定義的方法裏面 開啓嚴格模式 開啓嚴格模式後 this 就是 undefined 是 類 自動幫你開啓的
在constructor 裏 加一段代碼 以下
constructor(props) {
super(props)
this.state = {
isHot: true
}
// 解決 this 的指向問題
this.clickTitle = this.clickTitle.bind(this)
}
複製代碼
這個時候 咱們去控制檯 點擊標題 查看一下
this.clickTitle = this.clickTitle.bind(this) 這一段代碼 自己是一個賦值語句 咱們在實例對象自己加了一個方法 這個方法從那兒來的呢? 是從原型上來的
此處 咱們接着上一個小節中的內容 繼續 。
咱們將函數體的內容改成 以下 :
clickTitle() {
this.state.isHot = !this.state.isHot
}
複製代碼
運行項目後 發現 點擊標題依然不能改變標題的內容
咱們打印 函數裏的 this.state.isHot
會發現 isHot的值確實在改變 可是爲何頁面不更新呢
嚴重注意: state( 狀態 ) 不可直接更改, this.state.isHot = !this.state.isHot 這一行是錯誤的寫法
此處 咱們須要藉助 一個內置的 api 去更改state的值 setState() 。 咱們在函數體內打印 this 能夠找到
在函數體內修改以下代碼 :
clickTitle() {
this.setState({ isHot: !this.state.isHot })
}
複製代碼
這時 咱們點擊 頁面中的 標題 就能夠進行切換了
注意: 修改state的值 必須使用 setState 來修改, 且 修改是一個合併的動做 並非直接替換 setState調用幾回 render 這個方法就會調用幾回 能夠本身打印試試
將代碼改爲 以下:
import React, { Component } from 'react'
export default class App extends Component {
// constructor(props) {
// super(props)
// this.state = {
// }
// this.clickTitle = this.clickTitle.bind(this)
// }
state = {
isHot: true
}
// clickTitle() {
// this.setState({ isHot: !this.state.isHot })
// }
clickTitle = () => {
this.setState({ isHot: !this.state.isHot })
}
render() {
return (
<h2 onClick={this.clickTitle}>今每天氣很{this.state.isHot ? '炎熱' : '寒冷'}</h2>
)
}
}
複製代碼
此處 咱們將 state 從 constructor 直接拿出來
在類中 , 咱們直接寫一個賦值的語句 至關於 咱們在 APP 這個實例對象上 新加了一個屬性 屬性的名字 是 state 它的值是 { isHot:true }
而後 在將 this.clickTitle = this.clickTitle.bind(this) 給註釋掉
一樣 咱們在實例對象上 新增了一個方法 爲 clickTitle 值 是一個 箭頭 函數 這樣就解決掉了 this 的指向問題 避免在 constructor 頻繁的 使用bind 綁定this
將這兩行 註釋掉了之後 咱們徹底能夠將 constructor 這個構造器 給註釋掉, 由於咱們沒有在裏面寫任何的內容
如下爲完整代碼
import React, { Component } from 'react'
export default class App extends Component {
//初始化狀態
state = {
isHot: true
}
//自定義方法 須要採用 賦值語句的形式 + 箭頭函數
clickTitle = () => {
this.setState({ isHot: !this.state.isHot })
}
//渲染
render() {
return (
<h2 onClick={this.clickTitle}>今每天氣很{this.state.isHot ? '炎熱' : '寒冷'}</h2>
)
}
}
複製代碼