<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 狀態和生命周期 思考前面章節中提到的時鐘的例子。 迄今我們只了解了一種更新 UI 的方式。 我們通過調用 ReactDOM.render() 方法來更新渲染輸出: ~~~ function tick() { const element = ( <div> <h1>Hello, world!</h1> <h2>It is {new Date().toLocaleTimeString()}.</h2> </div> ); ReactDOM.render( element, document.getElementById('root') ); } setInterval(tick, 1000); ~~~ 在 CodePen 中[打開查看](http://codepen.io/gaearon/pen/gwoJZk?editors=0010)。 在本節中,我們將會了解如何使 Clock 組件真正可復用和封裝。它將設置自己的時鐘,并在每秒更新自身。 我們從封裝時鐘的外觀開始: ~~~ function Clock(props) { return ( <div> <h1>Hello, world!</h1> <h2>It is {props.date.toLocaleTimeString()}.</h2> </div> ); } function tick() { ReactDOM.render( <Clock date={new Date()} />, document.getElementById('root') ); } setInterval(tick, 1000); ~~~ 在 CodePen 中[打開查看它](http://codepen.io/gaearon/pen/dpdoYR?editors=0010)。 然而,它丟失了一個重要的需求:事實是, Clock 設置一個時鐘并每秒更新 UI 應該是 Clock 的實現細節。 理想情況下,我們希望只編寫一次,使 Clock 更新它自己: ~~~ ReactDOM.render( <Clock />, document.getElementById('root') ); ~~~ 要實現這點,我們需要添加 “state” 到 Clock 組件。 狀態和 props 類似,但是它是私有的,并且被組件完全控制。 我們之前提到的,組件定義為類有一些額外的功能。就是局部狀態:只有類組件可以用的特性。 ## 轉換功能組件為類組件 可以通過五部轉換一個像 Clock 這樣的功能組件為類組件: 1. 創建一個繼承 React.Component 類的 ES6 同名類 2. 添加一個空方法名為 render() 3. 把函數體移動到 render() 方法 4. 在 render() 方法中使用 this.props 替代 props 5. 刪除保留的空函數聲明 ~~~ class Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.props.date.toLocaleTimeString()}.</h2> </div> ); } } ~~~ 在 CodePen 中[打開查看](http://codepen.io/gaearon/pen/zKRGpo?editors=0010)。 Clock 現在被定義為一個 類組件 而不是功能組件。 這使我們可以使用如局部狀態和生命周期鉤子的額外功能。 ## 向一個類組件添加局部狀態 在有許多組件的應用中,非常重要的一點是當組件被銷毀的時候要釋放它們使用的資源。 我們希望無論何時 Clock 被首次渲染到 DOM 時[設置一個時鐘](https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval)。這在 React 中被稱為 “mounting”。 另外我們還希望當 Clock 生成的 DOM 被移除時[清除這個時鐘](https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/clearInterval)。在 React 中這叫做“unmounting”。 我們可以在組件類上聲明特定的方法,當組件 mounts 或者 unmouts 時運行一些代碼。 ~~~ class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } componentDidMount() { } componentWillUnmount() { } render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } } ~~~ 這些方法稱為“生命周期鉤子” componentDidMount() 鉤子在組件輸出被渲染到 DOM 之后運行。這是設置時鐘的不錯的位置: ~~~ componentDidMount() { this.timerID = setInterval( () => this.tick(), 1000 ); } ~~~ 注意我們如何保存時鐘 ID 在這里。 而 this.props 被 React 本身設置,this.state 有一個特定的意義,如果你需要保存一些不是用于視覺輸出的內容,你可以方便的手動添加額外的字段到類中。 如果你不在 render() 中使用什么,它不應該出現在 state 中。 我們將在 componentWillUnmount() 生命周期鉤子中拆除時鐘: ~~~ componentWillUnmount() { clearInterval(this.timerID); } ~~~ 最終,我們將會實現每秒運行的 tick() 方法。 它將使用 this.setState() 來安排組件局部狀態的更新: ~~~ class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } componentDidMount() { this.timerID = setInterval( () => this.tick(), 1000 ); } componentWillUnmount() { clearInterval(this.timerID); } tick() { this.setState({ date: new Date() }); } render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } } ReactDOM.render( <Clock />, document.getElementById('root') ); ~~~ 在 CodePen 中[打開查看](http://codepen.io/gaearon/pen/amqdNA?editors=0010)。 現在 Clock 的 tick() 將在每秒運行。 讓我們快速回顧以下其中的過程,和方法被調用的順序: 1. 當 `<Clock />` 被傳遞到 ReactDOM.render(), React 調用 Clock 組件的構造函數。由于 Clock 需要顯示當前時間,它使用一個包含當前時間的對象初始化了 this.state。我們之后會更新這個狀態。 2. React 之后會調用 Clock 組件的 render() 方法。這是 React 知道該顯示什么到屏幕的原因。React 之后匹配 Clock 的 render 輸出的內容來更新 DOM。 3. 當 Clock 輸出被插入到 DOM, React 調用 componentDidMount() 生命周期鉤子。其中,Clock 組件要求瀏覽器設置一個計時器來在每秒調用一次 tick() 。 4. 瀏覽器每秒都會調用 tick() 方法。在這里面, Clock 組件通過調用 setState() 并傳遞一個包含當前時間的對象來安排一個 UI 的更新。得益于 setState() 的調用,React 知道狀態被改變了,然后再次調用 render() 方法來了解什么應該顯示在屏幕中。這次,在render() 方法中的 this.state.date 將是不同的,所以 render 輸出中會包含更新的時間。React 對 DOM 進行相應的更新。 5. 如果 Clock 組件被從 DOM 中移除,React 調用 componentWillUnmount() 生命周期鉤子,所以計時器也會被停止。 ## 正確的使用狀態 關于 setState() 有三件事是你應該知道的。 ### 1.不要直接修改 state 例如,這將導致不能重新渲染組件: ~~~ // 錯誤用法 this.state.comment = 'Hello'; ~~~ 而是使用 setState() 替代: ~~~ // 正確用法 this.setState({comment: 'Hello'}); ~~~ 賦值 this.state 只有一個正確的地點,就是 constructor 中。 ### 2. 狀態更新可能是異步的 React 可能為了改進性能而批次處理多個 setState() 到一次更新。 因為 this.props 和 this.state 可能是異步更新的,你不能依賴他們的值計算下一個狀態。 例如,這段代碼可能導致更新 counter 失敗: ~~~ // 錯誤 this.setState({ counter: this.state.counter + this.props.increment, }); ~~~ 要彌補這個問題,使用另一種 setState() 的形式,它接受一個函數而不是一個對象。這個函數將接收前一個狀態作為第一個參數,應用更新時的 props 作為第二個參數: ~~~ // 正確 this.setState((prevState, props) => ({ counter: prevState.counter + props.increment })); ~~~ 我們在上面使用了一個[箭頭函數](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions),但是也可以使用一個常規的函數: ~~~ // 正確 this.setState(function(prevState, props) { return { counter: prevState.counter + props.increment }; }); ~~~ ### 3.狀態更新會被合并 當你調用 setState(), React 將合并你提供的對象到當前的狀態。 例如,你的狀態可能包含幾個獨立的變量: ~~~ constructor(props) { super(props); this.state = { posts: [], comments: [] }; } ~~~ 然后你可以在獨立的 setState() 調用中分別更新它們: ~~~ componentDidMount() { fetchPosts().then(response => { this.setState({ posts: response.posts }); }); fetchComments().then(response => { this.setState({ comments: response.comments }); }); } ~~~ 合并是淺層的,所以 this.setState({comments}) 保持 this.state.posts 的完整,但是完全替代了 this.state.comments 。 ## 數據流向 父組件和子組件都不能知道是否某個組件是有狀態的或無狀態的,它們也不應該在意它是被定義為一個功能組件還是一個類組件。 這是 state 經常稱為局部或者封裝的原因。它不能被除了擁有并設置它的另外的任何組件訪問。 一個組件可以選擇向下傳遞它的狀態作為它的子組件的 props : ~~~ <h2>It is {this.state.date.toLocaleTimeString()}.</h2> ~~~ 對于用戶定義的組件也同樣: ~~~ <FormattedDate date={this.state.date} /> ~~~ FormattedDate 組件可以接受它的 props 中的 date ,并不能知道它是否來自 Clock 的 state、props 或者是手動創建: ~~~ function FormattedDate(props) { return <h2>It is {props.date.toLocaleTimeString()}.</h2>; } ~~~ 在 CodePen 中[打開查看](http://codepen.io/gaearon/pen/zKRqNB?editors=0010)。 這通常稱為一個“從上到下”或者“單向”的數據流。任何狀態總是被某個特定的組件所有,任何被這個狀態驅動的數據或者 UI 都只影響樹中“下方”的組件。 如果你設想一個組件樹作為一個瀑布式的 props,每個組件的狀態都像一個額外的水源,然后在任意點匯入它,但是同樣只能向下流。 要展示這個,所有組件都是完全獨立的,我們一個 App 組件來渲染三個 `<Clock>`: ~~~ function App() { return ( <div> <Clock /> <Clock /> <Clock /> </div> ); } ReactDOM.render( <App />, document.getElementById('root') ); ~~~ 在 CodePen 中[打開查看](http://codepen.io/gaearon/pen/vXdGmd?editors=0010)。 每個 Clock 都設置它自己的計時器并獨立更新。 在 React App 中,一個組件是否是有狀態或者無狀態的,被認為是組件的一個實現細節,隨著時間推移可能發生改變。你可以在有狀態的組件中使用無狀態組件,反之亦然。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看