<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>

                # 前端組件化(二):優化 DOM 操作 > 作者:[胡子大哈](http://huziketang.com/books/react) </br> > 原文鏈接: [http://huziketang.com/books/react/lesson3](http://huziketang.com/books/react/lesson3) **轉載請注明出處,保留原文鏈接以及作者信息** 看看上一節我們的代碼,仔細留意一下?`changeLikeText`?函數,這個函數包含了 DOM 操作,現在看起來比較簡單,那是因為現在只有?`isLiked`?一個狀態。由于數據狀態改變會導致需要我們去更新頁面的內容,所以假想一下,如果你的組件依賴了很多狀態,那么你的組件基本全部都是 DOM 操作。 一個組件的顯示形態由多個狀態決定的情況非常常見。代碼中混雜著對 DOM 的操作其實是一種不好的實踐,手動管理數據和 DOM 之間的關系會導致代碼可維護性變差、容易出錯。所以我們的例子這里還有優化的空間:如何盡量減少這種手動 DOM 操作? ## 狀態改變 -> 構建新的 DOM 元素更新頁面 這里要提出的一種解決方案:一旦狀態發生改變,就重新調用?`render`?方法,構建一個新的 DOM 元素。這樣做的好處是什么呢?好處就是你可以在?`render`?方法里面使用最新的?`this.state`?來構造不同 HTML 結構的字符串,并且通過這個字符串構造不同的 DOM 元素。頁面就更新了!聽起來有點繞,看看代碼怎么寫,修改原來的代碼為: ~~~ class LikeButton { constructor () { this.state = { isLiked: false } } setState (state) { this.state = state this.el = this.render() } changeLikeText () { this.setState({ isLiked: !this.state.isLiked }) } render () { this.el = createDOMFromString(` <button class='like-btn'> <span class='like-text'>${this.state.isLiked ? '取消' : '點贊'}</span> <span></span> </button> `) this.el.addEventListener('click', this.changeLikeText.bind(this), false) return this.el } } ~~~ 其實只是改了幾個小地方: 1. `render`?函數里面的 HTML 字符串會根據?`this.state`?不同而不同(這里是用了 ES6 的模版字符串,做這種事情很方便)。 2. 新增一個?`setState`?函數,這個函數接受一個對象作為參數;它會設置實例的?`state`,然后重新調用一下?`render`?方法。 3. 當用戶點擊按鈕的時候,?`changeLikeText`?會構建新的?`state`?對象,這個新的?`state`?,傳入?`setState`?函數當中。 這樣的結果就是,用戶每次點擊,`changeLikeText`?都會調用改變組件狀態然后調用?`setState`?;`setState`?會調用?`render`?,`render`?方法會根據?`state`?的不同重新構建不同的 DOM 元素。 也就是說,你只要調用?`setState`,組件就會重新渲染。我們順利地消除了手動的 DOM 操作。 ## 重新插入新的 DOM 元素 上面的改進不會有什么效果,因為你仔細看一下就會發現,其實重新渲染的 DOM 元素并沒有插入到頁面當中。所以在這個組件外面,你需要知道這個組件發生了改變,并且把新的 DOM 元素更新到頁面當中。 重新修改一下?`setState`?方法: ~~~ ... setState (state) { const oldEl = this.el this.state = state this.el = this.render() if (this.onStateChange) this.onStateChange(oldEl, this.el) } ... ~~~ 使用這個組件的時候: ~~~ const likeButton = new LikeButton() wrapper.appendChild(likeButton.render()) // 第一次插入 DOM 元素 component.onStateChange = (oldEl, newEl) => { wrapper.insertBefore(newEl, oldEl) // 插入新的元素 wrapper.removeChild(oldEl) // 刪除舊的元素 } ~~~ 這里每次?`setState`?都會調用?`onStateChange`?方法,而這個方法是實例化以后時候被設置的,所以你可以自定義?`onStateChange`?的行為。這里做的事是,每當?`setState`中構造完新的 DOM 元素以后,就會通過?`onStateChange`?告知外部插入新的 DOM 元素,然后刪除舊的元素,頁面就更新了。這里已經做到了進一步的優化了:現在不需要再手動更新頁面了。 非一般的暴力,因為每次?`setState`?都重新構造、新增、刪除 DOM 元素,會導致瀏覽器進行大量的重排,嚴重影響性能。不過沒有關系,這種暴力行為可以被一種叫 Virtual-DOM 的策略規避掉,但這不是本文所討論的范圍。 這個版本的點贊功能很不錯,我可以繼續往上面加功能,而且還不需要手動操作DOM。但是有一個不好的地方,如果我要重新另外做一個新組件,譬如說評論組件,那么里面的這些?`setState`?方法要重新寫一遍,其實這些東西都可以抽出來,變成一個通用的模式。下一節我們把這個通用模式抽離到一個類當中。
                  <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>

                              哎呀哎呀视频在线观看