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オンデマンドシステムを構築

推薦する

javascript 入力画像のアップロードとプレビュー、FileReader プレビュー画像

FileReader は、フロントエンドのファイル処理、特に画像処理にとって重要な API です。画...

MySQLメモリストレージエンジンに関する知識

メモリストレージエンジンに関する知識ポイントメモリ ストレージ エンジンは日常業務ではほとんど使用さ...

XHTMLコードの一般的なアプリケーション問題をまとめる

時間が経つにつれて、多くの人が XHTML の使い方を知らないことに気づきました。普通の初心者だけで...

BootStrap グリッド間に隙間を残す解決策

目次[例を見る]: 【本来の効果は以下の通り】理由は次のとおりです。 【解決】:要約するBootSt...

Node8 における AsyncHooks 非同期ライフサイクル

Async Hooks は Node8 の新機能です。NodeJs の非同期リソースのライフサイクル...

NextCloud プライベート クラウド ストレージ ネットワーク ディスクの構築に関する詳細なチュートリアル

Nextcloud は、オープンソースで無料のプライベート クラウド ストレージ ネットワーク ディ...

CentOS8 でローカル yum ソースを構成するための詳細なチュートリアル

centos8 ディストリビューションは、BaseOS および AppStream リポジトリを通じ...

Mysql マルチテーブル結合クエリの実行の詳細について簡単に説明します。

まず、このブログのケースデモンストレーション テーブルを作成します。 create table a(...

Linux での感嘆符コマンド (!) の使用の概要

序文最近、弊社では mbp の設定をしており、ssh を使うことが多くなりました。複雑なコマンドを書...

insert と select を組み合わせて、「データベース内のフィールドの最大値 + 1 を挿入する」メソッドを実装する

この記事はmysqlデータベースです質問 1 表 1 のデータを表 2 にインポートします。表 1 ...

Centos7 への mysql8.0rpm のインストール チュートリアル

まず、図をダウンロードしてください 1. まず、centos7に付属しているmariadbをアンイン...

MySQL で 1000 万件のレコードをすばやくクエリする方法

目次通常のページングクエリ最適化する方法大きなオフセット使用ID制限大量データ問題の最適化通常のペー...

CSS スタイルの導入方法とその長所と短所の紹介

CSSを導入する3つの方法1. インラインスタイル利点: 書きやすく、重みがある 欠点: 構造とスタ...

シンプルなウェブデザインコンセプトのカラーマッチング

(I)ウェブページのカラーマッチングの基本概念(1)白黒の言葉は永遠のテーマです。誰もそれを悪く言う...

href をクリックした後にページがジャンプしないようにするための空のリンクの正しい書き方 # 問題

リンクを使用する必要がある場合もありますが、リンクする必要はありません。onclick イベントを処...