<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          用 Web Worker 提升30% Vue 組件性能【實例講解】

          共 4110字,需瀏覽 9分鐘

           ·

          2021-03-09 20:34


          關注公眾號 前端人,回復“加群

          添加無廣告優(yōu)質學習群


          有時開發(fā)者需要和一些“很重”的組件打交道 -- 這通常是指由于執(zhí)行了復雜的任務,所以創(chuàng)建和渲染開銷都很大的組件。

          比方說,我昨天就在使用“StoryBlok”工具庫創(chuàng)建富文本編輯器的時候遇到了麻煩。

          事情是這樣的,從 StoryBlok API 獲取富文本內容的時候,得到的數據有其獨有的結構。為了將這種數據渲染到 HTML 中,就必須使用 storyblok-js-client 庫提供的 richTextResolver.render(content) 方法。

          我們可以將這個功能封裝到一個 RichText.vue 組件中。一種基本的實現可能是:

          <template>
            <div v-html="contentHtml"></div>
          </template>

          <script>
            export default {
              props: ["content"],
              computed: {
                contentHtml() {
                  // $storyapi 是來自于 StoryBlok Nuxt.js 模塊中的一個實例
                  return this.$storyapi.richTextResolver.render(content);
                }
              }
            };
          </script>

          至此似乎平淡無奇,但...驚雷??不期而至。

          看上去,把這些內容渲染出來可是個繁重的工作,這在 StoryBlok 的各種組件開始渲染包含大量內容的數據時尤為明顯。

          現在再想象這樣的場景:你的頁面上有個包含富文本組件的列表,以及一個下拉篩選器。當你改變篩選項時,將重新請求符合篩選的所有內容,再把列表項都重新渲染一遍。

          實際運行后你還將看到 richTextResolver.render 帶來的渲染負擔:篩選下拉框在被選擇值后的關閉動作非常遲緩。

          原因就在于默認的 JavaScript 運行在主線程,也就是被稱作 UI-blocking 的問題。

          問題是理解了,但...如何解決呢?其實也很簡單:為富文本渲染任務使用一個 Web Worker 就行了。

          如果要對 JS 單線程和 Web Worker 有所了解,請閱讀:

          Web Worker 運行在一個獨立的線程中,且不會造成 UI 阻塞,非常適于我們的用例。

          worker-loader 插件

          更多的技術細節(jié)請閱讀上面的鏈接,這里只要知道 Web Worker 運行在自有的上下文中,并且默認情況無法訪問外部上下文就行了。但本例中我們要訪問到 storyblok-js-client npm 模塊。對此,可以用 Webpack 中的 worker-loader 解決。

          首先用  npm install -D worker-loader 安裝依賴。然后需要對其配置,比如在本例中的 Nuxt.js 中像這樣配置 nuxt.config.js :

          build: {
            extend(config, { isDev, isClient }) {
              config.module.rules.push({
                test/\.worker\.js$/,
                use: { loader"worker-loader" }
              });
            }
          }

          這樣一來,所有 .worker.js 結尾的文件都將被 worker-loader 注冊為 Web Worker

          下面創(chuàng)建一個 render-html.worker.js

          import StoryblokClient from "storyblok-js-client";

          let storyClient = new StoryblokClient({});

          self.addEventListener("message", ({ data }) => {
            const result = storyClient.richTextResolver.render(data);
            self.postMessage(result);
          });

          這就是一個 worker 的基礎實現。需要監(jiān)聽 message 事件,這也正是與你的 Vue.js 應用通訊的方式。當你從事件中得到 data 后,用 storyblok-js-client 渲染該數據,并將得到的結果用 self.postMessage 回傳。

          接著來升級一下 RichText.vue 組件,以使用以上 worker :

          <template>
            <div v-html="contentHtml"></div>
          </template>

          <script>
            import Worker from "./render-html.worker.js";

            const worker = new Worker();

            export default {
              props: ["content"],
              data: () => ({
                contentHtml: ""
              }),
              mounted() {
                // 等待處理好的 HTML 內容,并更新到狀態(tài)中
                worker.onmessage = ({ data }) => {
                  this.contentHtml = data;
                };
                // 將原始內容傳遞給 worker 渲染
                worker.postMessage(this.content);
              }
            };
          </script>

          結果

          你肯定很好奇,經過這一番折騰,性能上有何改善呢?看看就知道了。

          在 main.js 等處設置 Vue.config.performance = true 后,在 Chrome DevTools 里的 performance 選項卡中可查看性能監(jiān)測數據。

          結果分別是:組件渲染(創(chuàng)建 VDom 結構的時間)快了 20.65 倍、patch(將 VDom 結構應用到 DOM 上的時間)快了 1.39 倍。


          • 回復資料包領取我整理的進階資料包
          • 回復加群,加入前端進階群
          • console.log("點贊===看===你我都快樂")
          • Bug離我更遠了,下班離我更近了
          瀏覽 84
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产剧情一区二区 | 三级黄色国产高清电影 | 黄级网站特一免费观看 | 亚洲AV成人无码精品直播在线 | 操她在线|