Vue.js のパフォーマンス最適化に関する 9 つのヒント

1、機能部品

最初のトリックである機能コンポーネントについては、このライブサンプルをチェックしてください

最適化前のコンポーネントコードは次のとおりです。

<template>
  <div class="cell">
    <div v-if="value" class="on"></div>
    <section v-else class="off"></section>
  </div>
</template>

<script>
export default {
  props: ['value'],
}
</script>

最適化されたコンポーネント コードは次のとおりです。

<template functional>
  <div class="cell">
    <div v-if="props.value" class="on"></div>
    <section v-else class="off"></section>
  </div>
</template>

次に、各親コンポーネントで最適化の前後で 800 個のコンポーネントをレンダリングし、各フレーム内のデータを変更することでコンポーネントの更新をトリガーし、Chrome のパフォーマンス パネルを開いてパフォーマンスを記録し、次の結果を取得します。

最適化前:

最適化:

これら 2 つの図を比較すると、最適化前のscript実行また、JS エンジンはシングルスレッドの動作メカニズムであり、JS スレッドが UI スレッドをブロックすることがわかります。実行時間が長すぎると、レンダリングがブロックされ、ページがフリーズします。また、最適化されたscript実行時間は短いため、パフォーマンスが向上します。

では、なぜ機能部品JSを使用すると実行時間が短縮されるのでしょうか。これは機能コンポーネントの実装原理から始まり、渡されたコンテキスト データに従って DOM を描画および生成できる関数として理解できます。

機能部品は通常のオブジェクト型部品とは異なり、実部品とはみなされませんが、patchその過程ノードがコンポーネントであればvnodeサブ部品の初期化処理が再帰的に実行されることがわかっていますが、機能部品はrender生成されたもの正常でありvnode、再帰的なサブコンポーネントの処理がないため、レンダリングのオーバーヘッドは大幅に低くなります。

したがって、機能コンポーネントには状態、応答データ、およびライフサイクル フック関数もありません。これは、共通コンポーネント テンプレートから DOM の一部を取り除き、関数を通じてレンダリングするものと考えることができます。これは、DOM レベルでの一種の再利用です。

2、子コンポーネントの分割

2 番目のトリックであるサブコンポーネントの分割については、このオンライン例を確認してください

最適化前のコンポーネントコードは次のとおりです。

<template>
  <div :style="{ opacity: number / 300 }">
    <div>{
   
   { heavy() }}</div>
  </div>
</template>

<script>
export default {
  props: ['number'],
  methods: {
    heavy () {
      const n = 100000
      let result = 0
      for (let i = 0; i < n; i++) {
        result += Math.sqrt(Math.cos(Math.sin(42)))
      }
      return result
    }
  }
}
</script>

最適化されたコンポーネント コードは次のとおりです。

<template>
  <div :style="{ opacity: number / 300 }">
    <ChildComp/>
  </div>
</template>

<script>
export default {
  components: {
    ChildComp: {
      methods: {
        heavy () {
          const n = 100000
          let result = 0
          for (let i = 0; i < n; i++) {
            result += Math.sqrt(Math.cos(Math.sin(42)))
          }
          return result
        },
      },
      render (h) {
        return h('div', this.heavy())
      }
    }
  },
  props: ['number']
}
</script>

次に、各親コンポーネントで最適化の前後で 300 個のコンポーネントをレンダリングし、各フレーム内のデータを変更することでコンポーネントの更新をトリガーし、Chrome のパフォーマンス パネルを開いてパフォーマンスを記録し、次の結果を取得します。

最適化前:

最適化:

これら 2 つの数値を比較すると、最適化後のscript実行。

では、なぜ違いがあるのでしょうか? 最適化の前にコンポーネントを見てみましょう。この例では、heavy関数この関数はレンダリングされるたびに実行されるため、コンポーネントの各レンダリングには長い時間がかかりますJavaScript を実行する時間です。

最適化された方法はheavyChildCompこの時間のかかるタスク関数の実行ロジックをサブコンポーネントでカプセル化することです。Vue の更新はコンポーネントの粒度で行われるため、各フレームでデータ変更による親コンポーネントの再レンダリングが発生しChildCompます内部的には応答性の高いデータ変更がないため、再レンダリングされません。したがって、最適化されたコンポーネントはレンダリングのたびに時間のかかるタスクを実行することがなくなり、JavaScript の実行時間も自然に短縮されます。

ただし、この最適化方法については、いくつかの異なる意見を提出しました。詳細については、この問題をクリックしてください。このシナリオでの最適化のためのプロパティを計算することは、サブコンポーネントを分割するよりも優れていると思います。計算プロパティのキャッシュ機能のおかげで、時間のかかるロジックは最初のレンダリング時にのみ実行され、計算プロパティの使用時にサブコンポーネントのレンダリングに追加のオーバーヘッドが発生することはありません。

実際の業務では、コンピューティングのプロパティを使用してパフォーマンスを最適化するシナリオが多くありますが、結局のところ、それは空間を時間と交換するという最適化のアイデアも反映しています。

3、ローカル変数

3 番目のトリックであるローカル変数については、このオンライン例を確認してください

最適化前のコンポーネントコードは次のとおりです。

<template>
  <div :style="{ opacity: start / 300 }">{
   
   { result }}</div>
</template>

<script>
export default {
  props: ['start'],
  computed: {
    base () {
      return 42
    },
    result () {
      let result = this.start
      for (let i = 0; i < 1000; i++) {
        result += Math.sqrt(Math.cos(Math.sin(this.base))) + this.base * this.base + this.base + this.base * 2 + this.base * 3
      }
      return result
    },
  },
}
</script>

最適化されたコンポーネント コードは次のとおりです。

<template>
  <div :style="{ opacity: start / 300 }">{
   
   { result }}</div>
</template>

<script>
export default {
  props: ['start'],
  computed: {
    base () {
      return 42
    },
    result ({ base, start }) {
      let result = start
      for (let i = 0; i < 1000; i++) {
        result += Math.sqrt(Math.cos(Math.sin(base))) + base * base + base + base * 2 + base * 3
      }
      return result
    },
  },
}
</script>

次に、各親コンポーネントで最適化の前後で 300 個のコンポーネントをレンダリングし、各フレーム内のデータを変更することでコンポーネントの更新をトリガーし、Chrome のパフォーマンス パネルを開いてパフォーマンスを記録し、次の結果を取得します。

最適化前:

最適化:

これら 2 つの数値を比較すると、最適化後のscript実行。

これは主に、最適化前後のコンポーネントの計算プロパティresultの。最適化前のコンポーネントは計算プロセス中に何度もアクセスされますthis.baseが、最適化されたコンポーネントは計算前にローカル変数を使用しbase、キャッシュしthis.base、その後ローカル変数を使用します。後で直接アクセスしてくださいbase

では、なぜこの違いがパフォーマンスに違いをもたらすのでしょうか? その理由は、 は応答性の高いオブジェクトであるため、 にthis.baseアクセスするthis.baseトリガーされgetter、依存関係の収集に関連するロジック コードが実行されるためです。この例のように、数百サイクルで数百のコンポーネントを更新し、各コンポーネントがcomputed再計算依存関係収集関連のロジックを複数回実行するなど、同様のロジックを実行しすぎると、当然パフォーマンスが低下します。

要件としては、this.base依存関係収集を一度実行し、そのgetter評価、baseその後の再baseアクセスgetter依存関係収集のロジックに従わず、パフォーマンスが低下します。自然と改善されます。

これは非常に便利なパフォーマンス最適化手法です。なぜなら、多くの人が Vue.js プロジェクトを開発するとき、変数にアクセスするたびに習慣的に直接this.xxx書き込むから。これは、ほとんどの人がthis.xxxアクセスの背後で何が行われているかに気づかないためです。訪問数が少ない場合、パフォーマンスの問題は顕著ではありませんが、シナリオ例と同様に、大規模なループでの複数の訪問など、訪問数が増加すると、パフォーマンスの問題が発生します。

ZoomUI の Table コンポーネントのパフォーマンスを最適化するときにrender table body、ローカル変数最適化手法を使用し、パフォーマンス比較のためのベンチマークを作成しました。1000 * 10 のテーブルをレンダリングするとき、ZoomUI Table の更新されたデータを再レンダリングするパフォーマンスは次のようになります。 ElementUI の Table のパフォーマンスがほぼ 2 倍になりました。

4、v-showでDOMを再利用する

4 番目のトリックは、DOMv-showの再利用、このオンライン例を確認できます。

最適化前のコンポーネントコードは次のとおりです。

<template functional>
  <div class="cell">
    <div v-if="props.value" class="on">
      <Heavy :n="10000"/>
    </div>
    <section v-else class="off">
      <Heavy :n="10000"/>
    </section>
  </div>
</template>

最適化されたコンポーネント コードは次のとおりです。

<template functional>
  <div class="cell">
    <div v-show="props.value" class="on">
      <Heavy :n="10000"/>
    </div>
    <section v-show="!props.value" class="off">
      <Heavy :n="10000"/>
    </section>
  </div>
</template>

次に、各親コンポーネントで最適化の前後で 200 個のコンポーネントをレンダリングし、各フレーム内のデータを変更することでコンポーネントの更新をトリガーし、Chrome のパフォーマンス パネルを開いてパフォーマンスを記録すると、次の結果が得られます。

最適化前:

最適化:

これら 2 つの数値を比較すると、最適化後のscript実行。

最適化前後の主な違いはv-showv-ifコンポーネントの明示性を置き換えるコマンドの代わりにコマンドが使用されることです。パフォーマンスの点ではコンポーネントの明示性を制御するのv-showv-if似ていますが、それでも大きなギャップがあります。内部実装で。

v-if命令は、コンパイル フェーズ中に三項演算子と条件付きレンダリングにコンパイルされます。たとえば、最適化前のコンポーネント テンプレートは、次のレンダリング関数を生成するようにコンパイルされます。

function render() {
  with(this) {
    return _c('div', {
      staticClass: "cell"
    }, [(props.value) ? _c('div', {
      staticClass: "on"
    }, [_c('Heavy', {
      attrs: {
        "n": 10000
      }
    })], 1) : _c('section', {
      staticClass: "off"
    }, [_c('Heavy', {
      attrs: {
        "n": 10000
      }
    })], 1)])
  }
}

条件props.valueの、対応するコンポーネントの更新がトリガーされます。v-ifレンダリングされたノードの場合、古いノードと新しいノードvnodeが矛盾している、コア diff アルゴリズムの比較プロセス中に、古いvnodeノードが削除され、新しいvnodeノードが作成され、新しいHeavyコンポーネントはHeavyコンポーネントの初期化、レンダリングvnodeなどのプロセスを経ますpatch

そのため、コンポーネントが更新されるv-ifたびに新しいHeavyサブコンポーネントが作成されることになり、更新されたコンポーネントが多数存在すると、当然のことながらパフォーマンスの圧迫が生じます。

そして、v-showディレクティブを、最適化されたコンポーネント テンプレートがコンパイルされて、次のレンダリング関数が生成されます。

function render() {
  with(this) {
    return _c('div', {
      staticClass: "cell"
    }, [_c('div', {
      directives: [{
        name: "show",
        rawName: "v-show",
        value: (props.value),
        expression: "props.value"
      }],
      staticClass: "on"
    }, [_c('Heavy', {
      attrs: {
        "n": 10000
      }
    })], 1), _c('section', {
      directives: [{
        name: "show",
        rawName: "v-show",
        value: (!props.value),
        expression: "!props.value"
      }],
      staticClass: "off"
    }, [_c('Heavy', {
      attrs: {
        "n": 10000
      }
    })], 1)])
  }
}

条件props.valueの、対応するコンポーネントの更新がトリガーされます。v-showレンダリングされたノードの場合、古いノードと新しいノードvnodeは一貫している、patchVnode常に一致していれば十分です。では、DOM ノードはどのように表示されるのでしょうか?そして隠れますか?

プロセスでは、命令に対応するフック関数が内部で実行されそれが作用する DOM 要素の値を設定し、命令によってバインドされた値に従って表示と非表示を制御することがpatchVnodeわかります。v-showupdatev-showstyle.display

したがって、v-if常に、v-show既存の DOM の明示的および暗黙的な値を更新するだけであるため、v-showv-ifオーバーヘッドは のオーバーヘッドよりもはるかに小さく、内部 DOM 構造が複雑であればあるほど、オーバーヘッドは大きくなります。性能差になります。

v-showただしv-if、コンポーネントの更新フェーズでのパフォーマンスの利点と比較すると、初期化フェーズのみの場合は、1 つのブランチのみをレンダリングし、両方のブランチをレンダリングし、対応関係を制御するためv-if、パフォーマンスはそれよりも高くなります。DOM の可視性。v-showv-showstyle.display

v-show使用する、ブランチのすべての内部コンポーネントがレンダリングされ、対応するライフサイクル フック関数が実行さv-ifれます。一方、 を使用すると、ヒットしなかったブランチ内のコンポーネントはレンダリングされず、対応するライフサイクル フック関数は実行されません。

したがって、さまざまなシナリオで適切な命令を使用するには、それらの原則と違いを理解する必要があります。

5、キープアライブ

5 番目のトリックは、KeepAliveコンポーネントDOM をキャッシュする方法です。このオンライン サンプルをご覧ください。

最適化前のコンポーネントコードは次のとおりです。

<template>
  <div id="app">
    <router-view/>
  </div>
</template>

最適化されたコンポーネント コードは次のとおりです。

<template>
  <div id="app">
    <keep-alive>
      <router-view/>
    </keep-alive>
  </div>
</template>

ボタンをクリックしてシンプル ページとヘビー ページを切り替えると、さまざまなビューがレンダリングされますが、ヘビー ページのレンダリングには非常に時間がかかります。Chrome のパフォーマンス パネルを開いてパフォーマンスを記録し、最適化の前後に上記の操作を実行すると、次の結果が得られます。

最適化前:

最適化:

これら 2 つの数値を比較すると、最適化後のscript実行。

最適化されていないシナリオでは、ボタンをクリックしてルーティング ビューを切り替えるたびに、コンポーネントが再レンダリングされ、レンダリングされたコンポーネントに対してコンポーネントの初期化、およびその他のプロセスが実行されrenderますpatch。ネストが深くなると、全体のレンダリング時間が短縮され、非常に長くなります。

を使用するKeepAliveと、KeepAliveラップされたコンポーネントの最初のレンダリング後にvnodeとDOM がキャッシュされ、次回コンポーネントが再度レンダリングされるときに、対応vnodeする と DOM がキャッシュから直接取得されてレンダリングされます。コンポーネントの初期化などの一連のプロセスを実行することで、実行時間が短縮され、パフォーマンスが向上します。renderpatchscript

ただし、KeepAliveコンポーネントコストがかかります。キャッシュに必要なメモリが増えるためです。これは、時間に対する空間の最適化のアイデアの典型的な応用例です。

6、据え置き機能

6 番目のテクニックは、Deferredコンポーネントを遅延した方法でコンポーネントをバッチでレンダリングする方法で、このオンライン サンプルを確認できます。

最適化前のコンポーネントコードは次のとおりです。

<template>
  <div class="deferred-off">
    <VueIcon icon="fitness_center" class="gigantic"/>

    <h2>I'm an heavy page</h2>

    <Heavy v-for="n in 8" :key="n"/>

    <Heavy class="super-heavy" :n="9999999"/>
  </div>
</template>

最適化されたコンポーネント コードは次のとおりです。

<template>
  <div class="deferred-on">
    <VueIcon icon="fitness_center" class="gigantic"/>

    <h2>I'm an heavy page</h2>

    <template v-if="defer(2)">
      <Heavy v-for="n in 8" :key="n"/>
    </template>

    <Heavy v-if="defer(3)" class="super-heavy" :n="9999999"/>
  </div>
</template>

<script>
import Defer from '@/mixins/Defer'

export default {
  mixins: [
    Defer(),
  ],
}
</script>

ボタンをクリックしてシンプル ページとヘビー ページを切り替えると、さまざまなビューがレンダリングされますが、ヘビー ページのレンダリングには非常に時間がかかります。Chrome のパフォーマンス パネルを開いてパフォーマンスを記録し、最適化の前後に上記の操作を実行すると、次の結果が得られます。

最適化前:

最適化:

これら 2 つの図を比較すると、最適化前にシンプル ページからヘビー ページに切り替えると、レンダリングが終わりに近づいたときにページが依然としてシンプル ページとしてレンダリングされていることがわかります。これにより、ユーザーはページがフリーズしたように感じられます。最適化後、Simple Page から Heavy Page に切り替えると、Heavy Page は Render の先頭で 1 回レンダリングされており、Heavy Page は段階的にレンダリングされます。

最適化の前後の違いは主に、後者がDeferthis をmixin。どのように機能するか調べてみましょう。

export default function (count = 10) {
  return {
    data () {
      return {
        displayPriority: 0
      }
    },

    mounted () {
      this.runDisplayPriority()
    },

    methods: {
      runDisplayPriority () {
        const step = () => {
          requestAnimationFrame(() => {
            this.displayPriority++
            if (this.displayPriority < count) {
              step()
            }
          })
        }
        step()
      },

      defer (priority) {
        return this.displayPriority >= priority
      }
    }
  }
}

Deferの主なアイデアは、コンポーネントの 1 回のレンダリングを複数回に分割することです。内部的にdisplayPriority変数を、requestAnimationFrame各フレームをレンダリングするときにそれ自体を最大 まで増分しますcount次に、コンポーネントの内部Defer mixinを使用して、に追加されたときの特定のブロックのレンダリングv-if="defer(xxx)"displayPriority制御します。xxx

レンダリングに時間がかかるコンポーネントがある場合は、 JS の実行時間が長いためにレンダリングが停止するのを避けるために、プログレッシブ レンダリングDeferredを使用することをお勧めします。render

7、タイムスライス

7 番目の手法は、Time slicingタイム、このオンライン例を確認できます。

最適化前のコードは次のとおりです。

fetchItems ({ commit }, { items }) {
  commit('clearItems')
  commit('addItems', items)
}

最適化されたコードは次のとおりです。

fetchItems ({ commit }, { items, splitCount }) {
  commit('clearItems')
  const queue = new JobQueue()
  splitArray(items, splitCount).forEach(
    chunk => queue.addJob(done => {
      // 分时间片提交数据
      requestAnimationFrame(() => {
        commit('addItems', chunk)
        done()
      })
    })
  )
  await queue.start()
}

まずGenterate itemsボタン、次にボタンTime-slicingをクリックしてオンとオフのときにデータを送信し、Chrome のパフォーマンス パネルを開いてパフォーマンスを記録すると、次の結果が得られます。Commit items

最適化前:

最適化:

これら 2 つの数値を比較すると、script最適化前の合計実行時間はが、実際の外観と操作性から、最適化の前に送信ボタンをクリックすると、ページが約 1.2 秒間フリーズします。最適化後は、ページが完全に動かなくなるわけではありませんが、レンダリングの遅れは依然として感じられます。

では、なぜ最適化前にページがスタックしてしまうのでしょうか? 一度に送信されるデータが多すぎるため、内部 JS 実行時間が長すぎ、UI スレッドがブロックされ、ページがフリーズします。

最適化後も、分割したデータの粒度が 1000 であるため、ページはまだフリーズします。この場合、コンポーネントを再レンダリングするプレッシャーがまだあります。fps がわずか 12 であることが観察され、次のような感覚が得られます。氷結。通常、ページの fps が 60 に達していれば、ページは非常に滑らかになりますが、データ分割の粒度を 100 に変更すると、基本的に fps は 50 以上に達する可能性があります。 10,000データ完成 まだまだ時間がかかります。

Time slicing テクノロジーを使用すると、ページのスタックを回避できます。通常、この時間のかかるタスクを処理するときに読み込み効果を追加します。この例では、ページを開いてloading animationからデータを送信できます。比較の結果、最適化前は一度に送信されるデータが多すぎるため、JS が長時間実行されていて UI スレッドがブロックされており、この読み込みアニメーションは表示されませんが、最適化後は複数回に分割しているため、データを送信するためのスライス、単一の JS ランタイムが短縮されるため、読み込みアニメーションが表示される可能性があります。

ここで注意すべき点は、requestAnimationFrameタイム スライスを分割するために API を使用しますが、その使用requestAnimationFrame自体ではフルフレームの動作を保証できないrequestAnimationFrameということです。保証されるのは、対応する受信コールバック関数がブラウザの再描画のたびに実行されるということです。フルフレームでは、ティック内の JS の実行時間が 17 ミリ秒を超えないようにする必要があります。

8、非反応性データ

8 番目のヒントは、応答Non-reactive dataしない、このオンライン例を確認できます。

最適化前のコードは次のとおりです。

const data = items.map(
  item => ({
    id: uid++,
    data: item,
    vote: 0
  })
)

最適化されたコードは次のとおりです。

const data = items.map(
  item => optimizeItem(item)
)

function optimizeItem (item) {
  const itemData = {
    id: uid++,
    vote: 0
  }
  Object.defineProperty(itemData, 'data', {
    // Mark as non-reactive
    configurable: false,
    value: item
  })
  return itemData
}

引き続き前の例では、まずGenterate itemsボタン、次にボタンPartial reactivityをクリックして がオンになっているときとオフになっているときにデータを送信し、Chrome のパフォーマンス パネルを開いてパフォーマンスを記録します。次の結果が得られます。得られる。Commit items

最適化前:

最適化:

これら 2 つの数値を比較すると、最適化後のscript実行。

この違いの理由は、データが内部的に送信されるとき、新しく送信されたデータもデフォルトで応答性として定義されるためです。データのサブ属性がオブジェクトの形式である場合、再帰的にサブ属性が作成されます。属性もレスポンシブになるため、大量のデータを送信する場合にはこの処理に時間がかかります。

最適化後、新しく送信されたデータのオブジェクト属性をdata手動で に。これにより、 whenを通じて内部的に取得されたオブジェクト属性配列は無視され、このオブジェクトを指しているため、この属性ではなくなります。再帰的な応答性のロジックを減らすことは、この部分のパフォーマンスの損失を減らすことと同じです。データの量が大きくなるほど、この最適化の効果がより顕著になります。configurablefalsewalkObject.keys(obj)datadatadefineReactivedata

実際、このような最適化方法は他にもたくさんあります。たとえば、コンポーネントで定義した一部のデータは、必ずしもdataで。テンプレート内の一部のデータは使用せず、その変更を監視する必要もありません。このデータをコンポーネントのコンテキストで共有したいだけです。この時点では、データをコンポーネント インスタンスthis

export default {
  created() {
    this.scroll = null
  },
  mounted() {
    this.scroll = new BScroll(this.$el)
  }
}

こうすることで、リアクティブ オブジェクトではない場合でも、コンポーネント コンテキストでscrollオブジェクト。

9、仮想スクロール

9 番目のヒントでは、Virtual scrolling仮想、この実際の例を確認してください。

最適化前のコンポーネントのコードは次のとおりです。

<div class="items no-v">
  <FetchItemViewFunctional
    v-for="item of items"
    :key="item.id"
    :item="item"
    @vote="voteItem(item)"
  />
</div>

最適化されたコードは次のとおりです。

<recycle-scroller
  class="items"
  :items="items"
  :item-size="24"
>
  <template v-slot="{ item }">
    <FetchItemView
      :item="item"
      @vote="voteItem(item)"
    />
  </template>
</recycle-scroller>

View listまだ前の例ですが、それを開いて、Genterate itemsボタン10000 個の偽のデータを作成する必要があります(オンラインの例では最大 1000 個のデータしか作成できないことに注意してください。実際、1000 個のデータは最適化効果を十分に反映していないため、ソース コードの制限を変更し、ローカルで実行し、10,000 個のデータを作成しました) UnoptimizedボタンRecycleScrollerをクリックしてデータを送信し、ページをスクロールし、Chrome のパフォーマンス パネルを開いてパフォーマンスを記録すると、次の結果が得られます。Commit items

最適化前:

最適化:

この 2 枚の写真を比較すると、最適化なしの場合、10,000 データの fps がスクロールの場合は 1 桁、非スクロールの場合は 12 桁しかないことがわかりました。最適化されていないシーンでレンダリングされる DOM が多すぎるため、プレッシャー自体が非常に高くなります。最適化後は、データが 10,000 個であっても、スクロールの場合 fps は 30 以上、非ローリングの場合は 60 フル フレームに達する可能性があります。

この違いの理由は、仮想スクロールの実装ではビューポート内で DOM をレンダリングするだけであるため、レンダリングされる DOM の総量が非常に少なく、自然なパフォーマンスが大幅に向上するためです。

仮想スクロール コンポーネントもGuillaume Chauによって書かれており、興味のある学生はそのソース コードの実装を学ぶことができます。その基本原理は、スクロール イベントを監視し、表示される DOM 要素を動的に更新し、ビュー内でのそれらの変位を計算することです。

仮想スクロール コンポーネントにはコストがかかります。スクロール処理中にリアルタイムで計算する必要があるため、一定のscript実行。したがって、リスト内のデータ量がそれほど多くない場合は、通常のスクロールを使用するだけで十分です。

要約する

この記事を通じて、Vue.js の 9 つのパフォーマンス最適化テクニックを理解して、実際の開発プロジェクトに適用していただければ幸いです。上記の手法に加えて、画像の遅延ロード、コンポーネントの遅延ロード、非同期コンポーネントなどの一般的に使用されるパフォーマンス最適化方法もあります。

パフォーマンスの最適化を行う前に、ローカルの状況に適応できるように、パフォーマンスのボトルネックがどこにあるのかを分析する必要があります。さらに、パフォーマンスの最適化にはデータのサポートが必要であり、パフォーマンスの最適化を行う前に、最適化後のデータ比較を通じて最適化の効果を確認できるように、最適化前のデータを収集する必要があります。

今後の開発プロセスでは、実装要件に満足するだけでなく、コードの各行を記述する際にパフォーマンスに与える影響についても考慮していただければ幸いです。

この記事は最初に公開アカウント「Lao Huangのフロントエンドプライベートキッチン」に公開されたものです。ご注目ください。

著者:Huang Yi
リンク:https ://juejin.cn/post/6922641008106668045
出典:レアアースナゲット
著作権は著者に帰属します。商業的転載の場合は著者に連絡して承認を求め、非商業的転載の場合は出典を明記してください。

おすすめ

転載: blog.csdn.net/maxue20161025/article/details/128100068