React筆記5(State和生命周期)

回顧:
根據目前學習內容,更新界面內容的方法為ReactDOM.render()

//定義一個方法tick,包含組件和渲染
function tick(){
    const element = <h1>{new Date().toLocalTimeString()}</h1>
    ReactDOM.render(
        element,document.getElementById('root')
    )
}
//運行方法,每秒鐘重新構建元素和渲染,計時器效果
setInterval(tick,1000);
本次目的:實現(xiàn)clock組件的封裝和可重用

1.將函數轉換成class
①創(chuàng)建一個名為React.Component的ES6類
②創(chuàng)建一個render()的空方法
③把函數體移動到render(){}方法中
④在render方法中,使用this.props替換props
⑤刪除剩余的空函數聲明

class Clock extends React.Component{
    render(){
        return(
            <div>
                  <h1>{this.props.date.toLocaleTimeString()}</h1>
            </div>
        )
    }
}
ReactDOM.render(
    <Clock date={new Date()} />,
    document.getElementById('root')
)

現(xiàn)在Clock被定義為一個類,而不只是一個函數,
使用類就允許我們使用它的特性,例如局部狀態(tài),生命狀態(tài)鉤子。

1.為了一個類添加局部狀態(tài)

①將date從屬性中轉移到狀態(tài)中
②在render()方法張使用this.state.date代替this.props.date
③添加一個類構造函數來初始化State,類組件應始終用props調用基礎構造函數
④在Clock組件中,去除date屬性

class Clock extends React.Component{
    constructor(){
        super(props);
        this.state = {date:new Date()};
    }
    render(){
        return(
            <h1>it is {this.state.date.toLocalTimeString()}</h1>
        )
    }
}

ReactDOM.render(
    <Clock />,document.getElementById('root')
)

2.將生命周期方法添加到類中

在具有許多組件的應用程序中,銷毀時釋放組件所占用的資源非常重要。
每當Clock 組件加載到DOM中,都會想要用它生成一個定時器,在React中被稱為掛載
同樣,每當Clock生成的這個DOM被移除時,就需要清除定時器,這被稱為 卸載。
可以在組件中生命一些方法,當組件 掛載 或者 卸載時執(zhí)行。

class Clock extends React.Component{
    constructor(props){
        super(props);
        this.state = {date:new Date()};
    }
    componentDidMount(){
        console.log('掛載開始')
        this.timerID = setInterval(()=>{
            this.tick();
        },1000)
    }
    componentWillUnmounte(){
        console.log('結束')
        clearInterval(this.timerID);
    }
    tick(){
        this.setState({
            date:new Date()
        })
    }
    render(){
        return(
            <div>
                  <h1>{this.state.date.toLocaleTimeString()}</h1>
            </div>
        )
    }
}
ReactDOM.render(
    <Clock />,
    document.getElementById('root')
)

以上的componentDidMount()componentWillUnmount()方法被稱為生命周期鉤子
當組件輸出到DOM后會執(zhí)行componentDidMount()方法,這時候適合建立一個定時器
步驟如下:
①當 <Clock /> 被傳遞給 ReactDOM.render() 時,React 調用 Clock 組件的構造函數。 由于 Clock 需要顯示當前時間,所以使用包含當前時間的對象來初始化 this.state 。即this.state={date:new Date()};

②React 然后調用 Clock 組件的 render()方法。把React 更新 DOM 以匹配 Clock 的渲染輸出。

③當 Clock 的輸出插入到 DOM 中時,React 調用 componentDidMount()生命周期鉤子。 在其中,Clock 組件要求瀏覽器設置一個定時器,每秒鐘調用一次 tick(),此時DOM已經構建好,類似vue的mounted()。

④瀏覽器每秒鐘調用 tick()方法。 在其中,Clock 組件通過使用包含當前時間的對象調用 setState()來調度UI更新。 通過調用 setState(),React 知道狀態(tài)已經改變,并再次調用 render()方法來確定屏幕上應當顯示什么。 這一次,render()方法中的 this.state.date將不同,所以渲染輸出將包含更新的時間,并相應地更新DOM。

⑤一旦Clock組件被從DOM中移除,React會調用componentWillUnmount()這個鉤子函數,定時器也就會被清除。

從中可知:

修改this.state狀態(tài)需要使用this.setState({})方法,這里有點類似微信小程序的設置方式。

3.正確的使用狀態(tài)

關于this.setState({})的幾個重點
①更新狀態(tài)或者this.state中的內容

this.setState({comment:'hello'}); //正確修改方式
this.state.comment='hello' //錯誤方式
this.state.comment //獲取state狀態(tài)中的內容

②構造函數是唯一能夠初始化this.state的地方
③狀態(tài)的更新可能是異步操作導致的
React可以將多個setState({})調用合并成一個來提高性能。
因為this.propsthis.state可能是異步更新的,所以不應該根據這個來計算下一個狀態(tài)的值,因為可能不是最新的數據。

這里使用第二種形式
setState({})接收一個方法,而不是一個對象,其中包含2個參數,先前的狀態(tài)state作為第一個參數,應用被更新時的props作為第二個參數

// 錯誤的方式,計算的結果不是最新的
this.setState({
  counter: this.state.counter + this.props.increment,
});
// 正確的方式
this.setState((prevState,props)=>{
      counter:prevState.counter+props.increment
})

4.狀態(tài)的更新并合并

當使用this.setState的時候,React會將當前的提供的對象合并到當前狀態(tài)
狀態(tài)中可能包含一些獨立的變量

constructor(props){
    super(props);
    this.state({
        posts:[],
        comment:[]
    })
}

此時,可以分別調用```this.setState···獨立調用他們

  componentDidMount() {
    fetchPosts().then(response => {
      this.setState({
        posts: response.posts
      });
    });

    fetchComments().then(response => {
      this.setState({
        comments: response.comments
      });
    });
  }

5.數據的自頂向下流動

父組件或者子組件都不能知道其他組件是否有狀態(tài)state,以及組件是被定義為一個class類還是函數。
除了擁有并且設置他的組件外,其他組件不可訪問內部狀態(tài)。

組件可以選擇將他的狀態(tài)作為屬性傳遞給其他子組件。通過this.state來獲取

<h2>It is {this.state.date.toLocaleTimeString()}.</h2>

也適用于用戶自定義的組件

<hello date={this.state.date} />

其中hello組件收到的date屬性值,并不知道是來自Clock組件的屬性還是狀態(tài)。

這通常被稱為 自頂向下的數據流,或者是單向數據流。任何狀態(tài)始終只在某些特定的組件中,并且該狀態(tài)的導出的數據或者UI視圖,也只能影響 樹 下方的組件。

DEMO

為了證明所有組件都是隔離的,先創(chuàng)建一個組件<App />

class App extends React.Component{
    render(){
        return(
            <div>
                  <Clock />
                  <Clock />
                  <Clock />
            </div>
        )
    }
}

ReactDOM.render(
    <App />,document.getElementById('root')
)

其中的每一個<Clock />會建立自己的組件并且獨立更新。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • State 和生命周期 考慮前面章節(jié)中時鐘的例子。 到目前位置,我們僅學習了一種更新 UI 的方式。 我們調用Re...
    soojade閱讀 1,264評論 0 1
  • 想一下上一節(jié)中那個滴答計時的例子。迄今為止,我們只學到一種更新UI的方法。我們通過調用ReactDOM.rende...
    莫銘閱讀 583評論 0 0
  • 思考一下之前章節(jié)中的時鐘案例 到目前為止,我們只學習了一種更新UI的方式。 我們調用了ReactDOM.rende...
    __proto__閱讀 1,634評論 0 0
  • 客廳 簡練優(yōu)雅,如時光終未能淡去的黑白照片般灰階豐富,耐人尋味。 客廳 簾幕漫卷,濃情蜜意繾綣而來,又深埋于空氣中...
    泊焉未兆閱讀 266評論 0 0
  • 虹姐前言:虹姐又外出采訪了,這篇鴻篇巨制即是雞湯,又有干貨。還是老規(guī)矩,先介紹本文的男主。 男主本科學醫(yī)。是的。醫(yī)...
    虹姐說閱讀 1,859評論 4 8

友情鏈接更多精彩內容