Vue ファースト スクリーン パフォーマンス最適化コンポーネントの知識ポイントの概要

Vue ファースト スクリーン パフォーマンス最適化コンポーネントの知識ポイントの概要

Vue ファースト スクリーン パフォーマンス最適化コンポーネント

Vue ファースト スクリーン パフォーマンス最適化コンポーネントを実装するだけです。 最新のブラウザは多くの新しいインターフェイスを提供しています。 IE との互換性を考慮せずに、これらのインターフェイスを使用すると、コードの作成とパフォーマンスの最適化にかかる作業負荷を大幅に軽減できます。 もちろん、IE を考慮するために、コンポーネントをカプセル化するときに IE のバックアップを提供することもできます。 この記事のファースト スクリーン パフォーマンス最適化コンポーネントは、主に IntersectionObserver と requestIdleCallback の 2 つのインターフェイスを使用します。

説明する

まず、最初の画面のシナリオを考えてみましょう。表示を主な目的とした最初の画面を作成する場合、通常は画像などのリソースがさらに読み込まれます。ユーザーが開いたときにすべてのリソースを読み込むのではなく、コンポーネントを読み込む前にユーザーが関連する位置までスクロールするようにしたい場合は、IntersectionObserver インターフェイスを選択できます。もちろん、onscroll イベントを使用してリスナーを実行することもできますが、パフォーマンスが低下する可能性があります。ロードする必要があるコンポーネントもありますが、ページの初期化時に同期的にロードされないようにする必要があります。この方法では、Promise や setTimeout などの非同期メソッドを使用できます。ただし、このコンポーネントのロードの優先度を下げたい場合は、requestIdleCallback インターフェイスを検討できます。関連するコードは、https://github.com/WindrunnerMax/webpack-simple-environment の vue--first-screen-optimization ブランチにあります。

インターセクションオブザーバー

IntersectionObserver インターフェースは、Intersection Observer API に属し、ターゲット要素とその祖先要素または最上位ドキュメント ビューポートとの交差状態を非同期的に監視する方法を提供します。祖先要素とビューポートはルートと呼ばれます。つまり、IntersectionObserver API は要素が表示されているかどうかを自動的に監視できます。表示の本質は、ターゲット要素とビューポートが交差領域を生成することであるため、この API は交差オブザーバーと呼ばれます。互換性 https://caniuse.com/?search=IntersectionObserver。

const io = new IntersectionObserver(コールバック、オプション);

// 観察を開始します io.observe(document.getElementById("example"));
// 監視を停止します io.unobserve(element);
// オブザーバーを閉じます io.disconnect();
  • パラメータ callback は新しい IntersectionObserver オブジェクトを作成します。ターゲット要素の表示部分が 1 つ以上のしきい値を超えたことを検出すると、指定されたコールバック関数が実行されます。
  • パラメーター オプション、IntersectionObserver コンストラクターの 2 番目のパラメーターは構成オブジェクトであり、次のプロパティを設定できます。
  • しきい値属性は、コールバック関数がいつトリガーされるかを決定します。これは、各メンバーがしきい値である配列です。デフォルト値は[0]で、交差率が0に達したときにコールバック関数がトリガーされることを意味します。ユーザーはこの配列をカスタマイズできます。たとえば、[0、0.25、0.5、0.75、1]は、対象要素が0%、25%、50%、75%、100%表示されたときにコールバック関数がトリガーされることを意味します。
  • root 属性は、ターゲット要素が配置されているコンテナ ノード、つまりルート要素を指定します。ターゲット要素はウィンドウとともにスクロールするだけでなく、iframe ウィンドウ内でのスクロールのようにコンテナ内でもスクロールします。この場合、root 属性を設定する必要があります。コンテナ要素は、ターゲット要素の祖先ノードである必要があることに注意してください。
  • rootMargin属性はルート要素の余白を定義します。これはrootBounds四角形のサイズを拡大または縮小するために使用され、それによってintersectionRectの交差領域のサイズに影響を与えます。これは10px 20px 30px 40pxなどのCSS定義方法を使用し、上、右、下、左の方向の値を表します。
  • IntersectionObserver.root プロパティは読み取り専用で、監視対象オブジェクトの特定の祖先要素を参照します。値が渡されないか、値が null の場合、デフォルトで最上位のドキュメント ウィンドウが使用されます。
  • IntersectionObserver.rootMargin プロパティは読み取り専用です。これは、交差を計算するときにルート境界ボックスに追加される長方形のオフセットです。これにより、計算のニーズに合わせてルート決定範囲を効果的に縮小または拡大できます。このプロパティによって返される値は、コンストラクターの呼び出し時に指定された値と異なる場合があるため、内部要件に合わせて値を変更する必要がある場合があります。すべてのオフセットは、ピクセル (px) またはパーセンテージ (%) で表すことができます。デフォルト値は 0px 0px 0px 0px です。
  • IntersectionObserver.thresholds プロパティは読み取り専用で、しきい値を昇順で含むリストです。リスト内の各しきい値は、リスニング オブジェクトの交差領域と境界領域の比率です。リスニング オブジェクトのいずれかのしきい値を超えると、通知 Notification が生成されます。コンストラクターに値が渡されない場合、デフォルト値は 0 です。
  • IntersectionObserver.disconnect() メソッドは、IntersectionObserver オブジェクトの監視を停止します。
  • IntersectionObserver.observe() メソッドにより、IntersectionObserver はターゲット要素の監視を開始します。
  • メソッド IntersectionObserver.takeRecords() は、監視対象のすべてのターゲットの IntersectionObserverEntry オブジェクトの配列を返します。
  • IntersectionObserver.unobserve() メソッドは、IntersectionObserver による特定のターゲット要素の監視を停止します。

さらに、コールバック関数が実行されると、次の情報を提供する IntersectionObserverEntry オブジェクト パラメータが渡されます。

  • time: 可視性が変化する時間。ミリ秒単位の高精度のタイムスタンプです。
  • target: 監視対象のターゲット要素は DOM ノード オブジェクトです。
  • rootBounds: getBoundingClientRect メソッドの戻り値である、ルート要素の矩形領域に関する情報。ルート要素が存在せず、ビューポートに対して直接スクロールする場合は null が返されます。
  • boundingClientRect: 対象要素の矩形領域に関する情報。
  • intersectionRect: ターゲット要素とビューポートまたはルート要素間の交差領域に関する情報。
  • intersectionRatio: ターゲット要素の可視比率、つまり、intersectionRect と boundingClientRect の比率。完全に可視の場合は 1、完全に不可視の場合は 0 以下になります。
{
  時間: 3893.92、
  ルート境界: クライアントRect {
    下: 920、
    高さ: 1024,
    左: 0,
    右: 1024、
    上: 0,
    幅: 920
  },
  境界クライアント矩形: クライアント矩形 {
     // ...
  },
  交差点矩形:クライアント矩形{
    // ...
  },
  交差比率: 0.54、
  ターゲット: 要素
}

リクエストアイドルコールバック

requestIdleCallback メソッドは、ブラウザのアイドル期間中に呼び出される関数を受け入れることができます。これにより、開発者は、アニメーションや入力応答などの遅延されたキー イベントに影響を与えることなく、メイン イベント ループでバックグラウンドおよび低優先度の作業を実行できます。関数は通常、先入れ先出しの順序で実行されます。コールバック関数で実行タイムアウトが指定されている場合は、タイムアウト前に関数を実行するために実行順序を乱すことが可能です。互換性 https://caniuse.com/?search=requestIdleCallback。

const ハンドル = window.requestIdleCallback(コールバック[, オプション]);
  • requestIdleCallback メソッドは ID を返します。この ID を window.cancelIdleCallback() メソッドに渡すと、コールバックを終了できます。
  • パラメータ callback は、イベント ループがアイドル状態のときに呼び出される関数への参照です。この関数は、IdleDeadline というパラメータを受け取ります。このパラメータによって、現在のアイドル時間と、タイムアウト前にコールバックが実行されたかどうかを取得できます。
  • パラメータ オプションはオプションであり、次のプロパティを持つオプションの構成パラメータが含まれます。
  • timeout: timeout が指定され、正の値を持ち、timeout ミリ秒が経過してもコールバックが呼び出されなかった場合、パフォーマンスに悪影響を与える可能性がある場合でも、コールバック タスクはイベント ループのキューに入れられます。

成し遂げる

実際、コンポーネントの作成では、主にこれら 2 つの主要な API の使用方法を理解する必要があります。まず、IntersectionObserver に注目しましょう。動的コンポーネント <component /> を使用する必要があるため、これに値を渡すときに、非同期コンポーネント読み込み () => import("component") 形式を使用する必要があります。リスニングする場合、読み込みが完了したらリスナーを破棄するか、視覚領域を離れたら破棄するかなどが考えられます。これは主に戦略的な問題です。ページが破棄されると、メモリ リークを防ぐために Intersection Observer を切断する必要があります。 requestIdleCallback の使用は比較的簡単です。Promise.resolve().then の非同期処理に似たコールバック関数を実行するだけです。

簡単な実装ロジックを以下に示します。通常、オブザーバーの使用方法は、まず div をプレースホルダーとして使用し、次にオブザーバーでプレースホルダーのコンテナーを監視します。コンテナーがビューポートにある場合、関連するコンポーネントを読み込みます。関連するコードは、https://github.com/WindrunnerMax/webpack-simple-environment の vue--first-screen-optimization ブランチにあります。インストールには yarn を使用してみてください。依存関係の問題を回避するために、yarn.lock ファイルを使用してバージョンをロックできます。 npm run dev で実行すると、Console でこれら 4 つの遅延ロード コンポーネントが作成される順序を確認できます。このうち、A のオブザーバーの遅延ロードは、ロード中のページがレンダリングされ、可視領域にあると判断されてからロードする必要があるため、最初の画面で直接見ることができます。D の遅延ロードは、D の外部コンテナーがビューに表示されるまでスクロール バーをスライドしてから表示する必要があります。つまり、D コンポーネントは一番下までスクロールしないと読み込まれません。また、$attrs と $listeners と同様に、component-params と component-events を通じて、遅延ロード コンポーネントに attrs と listeners を渡すこともできます。この時点で、遅延ロード コンポーネントが簡単に実装されました。

<!-- App.vue -->
<テンプレート>
    <div>
        <セクション>1</セクション>
        <セクション>
            <div>2</div>
            <遅延読み込み
                :lazy-component="例"
                タイプ="オブザーバー"
                :component-params="{ content: '例A' }"
                :コンポーネントイベント="{
                    'テストイベント': テストイベント、
                }"
            </遅延読み込み>
        </セクション>
        <セクション>
            <div>3</div>
            <遅延読み込み
                :lazy-component="例"
                タイプ="アイドル"
                :component-params="{ content: '例 B' }"
                :コンポーネントイベント="{
                    'テストイベント': テストイベント、
                }"
            </遅延読み込み>
        </セクション>
        <セクション>
            <div>4</div>
            <遅延読み込み
                :lazy-component="例"
                タイプ="lazy"
                :component-params="{ content: '例 C' }"
                :コンポーネントイベント="{
                    'テストイベント': テストイベント、
                }"
            </遅延読み込み>
        </セクション>
        <セクション>
            <div>5</div>
            <遅延読み込み
                :lazy-component="例"
                タイプ="オブザーバー"
                :component-params="{ content: '例 D' }"
                :コンポーネントイベント="{
                    'テストイベント': テストイベント、
                }"
            </遅延読み込み>
        </セクション>
    </div>
</テンプレート>

<script lang="ts">
「vue-property-decorator」から Component、Vue をインポートします。
「./components/lazy-load/lazy-load.vue」からLazyLoadをインポートします。
@成分({
    コンポーネント: { LazyLoad },
})
デフォルトクラスAppをエクスポートし、Vueを拡張します。
    保護された Example = () => import("./components/example/example.vue");

    保護されたテストイベント(コンテンツ: 文字列) {
        console.log(コンテンツ);
    }
}
</スクリプト>

<スタイル lang="scss">
@import "./common/styles.scss";
体 {
    パディング: 0;
    マージン: 0;
}
セクション {
    マージン: 20px 0;
    色: #fff;
    高さ: 500px;
    背景: $color-blue;
}
</スタイル>
コピー
<!-- 遅延ロード.vue -->
<テンプレート>
    <div>
        <コンポーネント
            :is="レンダリングコンポーネント"
            v-bind="コンポーネントパラメータ"
            v-on="コンポーネントイベント"
        </コンポーネント>
    </div>
</テンプレート>

<script lang="ts">
「vue-property-decorator」から { Component、Prop、Vue } をインポートします。
@成分
デフォルトのクラスLazyLoadをエクスポートし、Vueを拡張します。
    @Prop({ タイプ: 関数、必須: true })
    lazyComponent!: () => Vue;
    @Prop({ 型: 文字列、必須: true })
    タイプ: "オブザーバー" | "アイドル" | "レイジー";
    @Prop({ 型: Object、デフォルト: () => ({}) })
    コンポーネントパラメータ: Record<文字列、不明>;
    @Prop({ 型: Object、デフォルト: () => ({}) })
    コンポーネントイベント!: Record<文字列、不明>;

    保護されたオブザーバー: IntersectionObserver | null = null;
    保護された renderComponent: (() => Vue) | null = null;

    保護されたマウント() {
        これを初期化します。
    }

    プライベートinit() {
        if (this.type === "オブザーバー") {
            // `window.IntersectionObserver` が存在する
            if (window.IntersectionObserver) {
                this.observer = 新しい IntersectionObserver(entries => {
                    エントリ.forEach(item => {
                        // `intersectionRatio` は対象要素の可視比率で、`0` より大きい場合は可視であることを意味します // ロード後に `observe` を解放せず、不可視の場合は破棄するなど、実装戦略の問題もあります。 if (item.intersectionRatio > 0) {
                            コンポーネントをロードします。
                            // 読み込みが完了したら、`observe` のチェックを外します
                            this.observer?.unobserve(item.target);
                        }
                    });
                });
                this.observer.observe(this.$el.parentElement || this.$el);
            } それ以外 {
                // 直接ロードします this.loadComponent();
            }
        } そうでない場合 (this.type === "idle") {
            // `requestIdleCallback` が存在する
            // eslint 次の行を無効にする @typescript-eslint/ts コメントを禁止
            // @ts を無視
            if (window.requestIdleCallback) {
                リクエストIdleCallback(this.loadComponent, { タイムアウト: 3 });
            } それ以外 {
                // 直接ロードします this.loadComponent();
            }
        } そうでない場合 (this.type === "lazy") {
            // `Promise` が存在する
            if (window.Promise) {
                Promise.resolve().then(this.loadComponent);
            } それ以外 {
                // `setTimeout` を使用するようにダウングレードします
                タイムアウトを設定します(this.loadComponent);
            }
        } それ以外 {
            新しいエラーをスローします(`type: "observer" | "idle" | "lazy"`);
        }
    }

    プライベートloadComponent() {
        this.renderComponent を this.lazyComponent に追加します。
        this.$emit("ロードされました");
    }

    保護された破棄() {
        this.observer && this.observer.disconnect();
    }
}
</スクリプト>

毎日の質問

https://github.com/WindrunnerMax/EveryDay

参照する

https://www.ruanyifeng.com/blog/2016/11/intersectionobserver_api.html

https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserver

https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestIdleCallback

これで、Vue のファースト スクリーン パフォーマンス最適化コンポーネントのナレッジ ポイントのまとめに関する記事は終了です。Vue のファースト スクリーン パフォーマンス最適化コンポーネントの関連コンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Vue プロジェクトの最初の画面のパフォーマンス最適化コンポーネントの実践ガイド
  • Vue.js パフォーマンス最適化 N 個のヒント (収集する価値あり)
  • Vue2.x プロジェクトのパフォーマンス最適化のためのコード最適化の実装
  • vueプロジェクトはGzip圧縮とパフォーマンス最適化操作を可能にします
  • Vue のパフォーマンスを最適化する方法
  • Vueコンポーネントのレンダリングを高速化し、パフォーマンスを最適化します

<<:  CSS3で背景画像にカラーマスクを追加する方法

>>:  Docker、プレーヤー機能を備えたCMSオンデマンドシステムを構築

推薦する

Windows システムに MySQL を素早くインストールして展開する方法 (グリーンの無料インストール バージョン)

まずは緑色の無料インストール版のMySQLをダウンロードします。任意のフォルダに入れて構いません。今...

MySQL データ型の完全分析

データ型: 列に格納できるデータとそのデータが実際にどのように格納されるかを定義する基本ルール。デー...

プロファイルを使用して遅い SQL を分析する MySQL の詳細な説明 (グループ左結合はサブクエリよりも効率的です)

プロファイルを使用して遅いSQLを分析するMySQL の SQL パフォーマンス アナライザーの主な...

MySQL ビッグデータ クエリ最適化エクスペリエンスの共有 (推奨)

本格的な MySQL 最適化! MySQL のデータ量が少ない場合は最適化は不要です。データ量が多い...

さまざまなブラウザでのhrタグの説明

通常、人事担当者と会うことはめったにありませんが、一度会うと、それが生死を分けることもあります。 H...

Podmanはコンテナを自動的に起動し、Dockerと比較します

目次1. podmanの紹介2. Dockerと比較した利点3. 互換性4. バックグラウンド サー...

MySQL 5.7.13 のインストールと設定方法の Mac でのグラフィック チュートリアル

MySQL 5.7.13 Mac用インストールチュートリアル、非常に詳細で、以下のように記録されてい...

GolangでMySQLデータベースのバックアップを実装する方法

背景Navicat は、最高の MySQL 視覚化ツールです。ただし、ビューのインポートとエクスポー...

ファイル操作のためのLinuxシステムコール

目次1. ファイルを開くパラメータの紹介2. ファイルの読み取り3. ファイルを書き込む4. 閉じる...

Centos7 環境でバイナリ インストール パッケージから mysql5.6 をインストールする方法の詳細な説明

この記事では、centos7 環境でバイナリ インストール パッケージを使用して mysql5.6 ...

CSS を使用してテクスチャ付きグラデーション背景画像を記述するためのサンプル コード

プロジェクト内のページの長さはおよそ2000px以上あり、背景画像にはテクスチャやグラデーションがあ...

Javascript 非同期プログラミング: Promise を本当に理解していますか?

目次序文基本的な使い方文法エラー処理プロミスチェーン呼び出し非同期と待機よく使われる方法1. Pro...

JS は Baidu 検索ボックスを実装します

この記事の例では、Baidu検索ボックスを実装するためのJSの具体的なコードを参考までに共有していま...

MySQLデータベースで列を追加、削除、変更する方法

この記事では、例を使用して、MySQL データベースの列を追加、削除、および変更する方法について説明...

Chrome 73 によるフレックスレイアウトの崩れの解析と解決方法

現象プロジェクトにはネストされたフレックス構造がいくつかあります。 <スタイル> /* ...