vue3.2 で追加された defineCustomElement の基本原理の詳細な説明

vue3.2 で追加された defineCustomElement の基本原理の詳細な説明

Webコンポーネント

Web コンポーネントは、再利用可能なカスタム要素 (その機能はコード外部にカプセル化されています) を作成し、Web アプリケーションで使用できるようにするさまざまなテクノロジのセットです。

これは、VueやReactなどのフレームワークを通じてコン​​ポーネント定義を実装する必要がなく、ブラウザのネイティブなコンポーネント定義方法と同等です。

カスタム要素

概要

customElements は、Window オブジェクトの読み取り専用プロパティです。このインターフェイスは、CustomElementRegistry オブジェクトへの参照を返します。このオブジェクトは、新しいカスタム要素を登録したり、以前に定義されたカスタム要素に関する情報を取得したりするために使用できます。

HTMLTemplateElement コンテンツ テンプレート要素

概要

HTML <template> 要素は、ページの読み込み時にはレンダリングされないが、実行時に JavaScript を使用してインスタンス化される可能性のあるクライアント側コンテンツを保持するためのメカニズムです。
テンプレートは、後で使用するためにドキュメントに保存できるコンテンツの一部と考えてください。パーサーはページを読み込むときに <template> 要素のコンテンツを処理しますが、そのコンテンツが有効であることを確認するためだけに処理し、要素のコンテンツはレンダリングされません。

共通プロパティ

content DocumentFragment 要素フラグメントのコンテンツを取得します。これは、document.createDocumentFragment() によって作成された要素フラグメントと同等です。

  <!-- テンプレートフラグメントを定義します -->
  <テンプレートid="要素テンプレート">
    <div>テストテンプレート</div>
  </テンプレート>

  <スクリプト>
    /* テンプレートフラグメントを取得します */
    const ele = document.getElementById('要素テンプレート')
    ele.content インスタンス DocumentFragment //true

    /* createDocumentFragment で HTML フラグメントを作成する*/
    定数div = document.createDocumentFragment('div')
    div インスタンス DocumentFragment //true

    /* 結論は*/
    // HTML で定義されたテンプレートは、createDocumentFragment によって作成された HTML フラグメントと同等のコンテンツを取得します</script>

シャドウルート

概要

Shadow DOM API の ShadowRoot インターフェースは、ドキュメントのメイン DOM ツリーとは別にレンダリングされる DOM サブツリーのルート ノードです。
モードを open に設定して Element.attachShadow() で作成されたと仮定すると、Element.shadowRoot プロパティを使用して要素への参照を取得できます。

Element.attachShadow() 経由でシャドウ DOM をマウントします。

完全なデモコード

<!DOCTYPE html>
<html lang="ja">
<ヘッド>
  <メタ文字セット="UTF-8">
  <meta name="viewport" content="width=デバイス幅、初期スケール=1.0">
  <title>ドキュメント</title>
</head>
<本文>

  <テストシャドウルート><​​/テストシャドウルート>

  <テンプレートid="templateEle">
    <スタイル>
      。主要{
        色: #f00;
      }
    </スタイル>
    <div class="main">
      私はテンプレートフラグメントです<!-- スロットの使用 -->
      <スロット名="ヘッダー"></スロット>
    </div>
  </テンプレート>
  <テストテンプレート要素>
    <!-- スロットを定義する -->
    <スタイル>
      。スロット{
        色: rgb(87, 28, 223);
      }
    </スタイル>
    <div class="slot" slot="header">私はスロットです</div>
  </テストテンプレート要素>

  <!-- ライフサイクルテスト -->
  <div id="moveDiv">
    <button id="add">追加</button>
    <button id="update">更新</button>
    <button id="move">移動</button>
    <button id="remove">削除</button>
  </div>

  <!-- マウントは -->
  <div is="test-is-com">
    <div>AAA</div>
  </div>


  <スクリプト>
    /* カスタム Web コンポーネント */
    customElements.define('test-shadow-root', クラスはHTMLElementを拡張します {
      /* test-shadow-root コンポーネントが DOM にマウントされたら、コンストラクタを実行します */
      コンストラクタ() {
        素晴らしい()
        const shadowRoot = this.attachShadow({mode: 'open'}) //指定された要素にシャドウDOMをアタッチします
        // this.attachShadow() メソッドが実行されると、shadowRoot がコンストラクターにマウントされ、これを介してアクセスできるようになります // モード open のシャドウ ルート要素は、js の外部からルート ノードにアクセスできます // モード closed は、js の外部からのクローズ シャドウ ルート ノードへのアクセスを拒否します // console.log('execution', this)
        定数div = document.createElement('div')
        div.textContent = '私はdivのコンテンツです'
        // shadowRoot.appendChild()
        // console.log('this', this.shadowRoot)
        shadowRoot.appendChild(div)
        // this.shadowRoot === shadowRoot は true
      }
    })

    /* テンプレートを通じて HTMLTemplateElement をカスタマイズする */
    customElements.define('test-template-ele', クラスは HTMLElement を拡張します {
      コンストラクタ() {
        素晴らしい()
        const temEle = document.querySelector('#temEle')
        const templateContent = temEle.content // HTML フラグメントを取得します // console.log('AA', templateContent instanceof DocumentFragment) //true
        // テンプレートコンテンツ
        // テンプレートフラグメントをマウントするためのシャドウDOMを作成する const shadowRoot = this.attachShadow({mode: 'open'})
        // コンソールログ('shadowRoot', shadowRoot)
        shadowRoot.appendChild(テンプレートコンテンツ)
      }
    })

    /* js を通じて Web コンポーネントを作成し、ライフサイクル関数をテストします */
      クラスLifeCycleはHTMLElementを拡張します。
        static get observedAttributes() { // attributeChangedCallback をトリガーするには、コンポーネントに属性を追加する必要があります
          ['c', 'l'] を返します。
        }

        コンストラクタ() {
          素晴らしい()
          const shadowRoot = this.attachShadow({mode: 'open'})
          const div = `<div>
            <header>私の頭</header>
            <div>コンテンツ</div>
            <footer>テール</footer>
          </div>`
          shadowRoot.innerHTML = div
        }

        connectedCallback() { //追加するときはconsole.log('add')を実行します
        }
        disconnectedCallback() //削除する場合はconsole.log('disconnectedCallback')を実行
        }
        採用されたコールバック() {
          console.log('採用されたコールバック')
        }
        attributeChangedCallback() { //属性が変更されると、console.log('attributeChangedCallback')
        }
      }

      customElements.define('テストライフサイクル', ライフサイクル)

      定数 add = document.querySelector('#add')
      定数更新 = document.querySelector('#update')
      const 移動 = document.querySelector('#move')
      定数remove = document.querySelector('#remove')
      const moveDiv = document.querySelector('#moveDiv')
      testLifeDom = null とします

      関数ランダム(最小値, 最大値) {
        Math.floor(Math.random() * (max - min + 1) + min) を返します。
      }

      add.addEventListener('クリック', () => {
        testLifeDom = document.createElement('test-life-cycle') //上記で定義したカスタムコンポーネントを作成します // ​​console.log('testLifeDom', testLifeDom)
        document.body.appendChild(testLifeDom);
        testLifeDom.setAttribute('l', '100');
        testLifeDom.setAttribute('c', 'red');
        コンソールログ('add'、testLifeDom)
      })

      更新.addEventListener('クリック', () => {
        const div = '<div>更新されました</div>'
        // console.log('update', testLifeDom.shadowRoot.innerHTML)
        testLifeDom.shadowRoot.innerHTML = div
        testLifeDom.setAttribute('l', ランダム(50, 200));
        testLifeDom.setAttribute('c', `rgb(${random(0, 255)}, ${random(0, 255)}, ${random(0, 255)})`);
      })

      move.addEventListener('クリック', () => {
        コンソールログ('moveDiv', moveDiv)
        移動Div.appendChild(testLifeDom)
      })

      削除.addEventListener('クリック', () => {
        コンソールログ('削除')
        document.body.removeChild(testLifeDom);
      })

      /* is 経由でコンポーネントをマウントする*/

      customElements.define('test-is-com', クラスは HTMLDivElement を拡張します {
        コンストラクタ() {
          素晴らしい()
          console.log('マウント', this.innerHTML)
          // マウントにより、これは現在マウントされている要素インスタンスになります。この方法で、いくつかの操作を実装できます。}
      }, {extends: 'div'})

  </スクリプト>
</本文>
</html>

これで、vue3.2 で追加された defineCustomElement の基本原理に関するこの記事は終了です。vue3.2 の defineCustomElement に関するより関連性の高いコンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後も 123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • レスポンシブ原則をシミュレートするための基礎コードの Vue 実装の例
  • Vueデータ双方向バインディングの基本的な実装原則
  • Vue の基本的な実装原則の概要
  • Vue の基本原理についてどれくらい知っていますか?

<<:  テーブルを作成するための MySQL SQL ステートメントの詳細な概要

>>:  CentOS7でXShellとネットワーク設定を接続する方法

推薦する

JavaScriptの基本的なインタラクションの詳細な説明

目次1. 要素の入手方法文書から入手ID取得クラス名 (className) を取得します。タグ名 ...

Vue 手書き読み込みアニメーション プロジェクト

ページが応答しない場合、白い画面が表示されないように、読み込みアニメーションを表示するのがユーザーフ...

JavaScript におけるブラウザ互換性の問題について簡単に説明します

ブラウザの互換性は、実際の開発では見落とされがちな最も重要な部分です。古いバージョンのブラウザの互換...

Nginx をインストールして複数のドメイン名を設定する方法

Nginx のインストールCentOS 6.x yum にはデフォルトで nginx ソフトウェア ...

MySQL マスターライブラリ binlog (master-log) とスレーブライブラリ relay-log 間のコードの詳細な説明

メインライブラリのバイナリログ: # 2420 で #170809 17:16:20 サーバー ID...

Faint: 「Web2.0 を使用して標準に準拠したページを作成する」

今日、ある人がウェブサイト開発プロジェクトについて話をしてくれました。具体的な要件について話すと、「...

MySQLコンテナ間のレプリケーション構成例の詳細な説明

背景先週、会社で MySQL レプリケーションのトレーニングを受けたので、今週末は学んだことを実践す...

HTML の空リンク href="#" と href="javascript:void(0)" の違い

# には位置情報が含まれます。デフォルトのアンカーは #top で、これは Web ページの上部です...

Linux 向けの強化されたスクリーンショットと共有ツール: ScreenCloud

ScreenCloud は、必要だとは思わなかった素晴らしい小さなアプリです。デスクトップ Lin...

ウェブページの読み込み速度を上げる25の方法とヒント

はじめに<br />誰もが高速インターネット接続にアクセスできるわけではありません。たと...

CentOS はローカル yum ソースを使用して LAMP 環境を構築するグラフィック チュートリアル

この記事では、ローカル yum ソースを使用して CentOS 上に LAMP 環境を構築する方法に...

CentOS7 は yum を使用して mysql 8.0.12 をインストールします

この記事では、centos7にyumを使用してMySQL 8.0.12をインストールする詳細な手順を...

Zabbix を使用して Nginx/Tomcat/MySQL を監視する方法の詳細なチュートリアル

目次ZabbixはNginxを監視するZabbixはTomcatを監視するZabbixはMySQLを...

MySQLにおける時刻日付型と文字列型の選択について

目次1. DATETIMEとTIMESTAMPの使用1. 類似点2. 相違点3. 選択2. varc...

純粋なJSを使用してセカンダリメニュー効果を実現します

この記事の例では、セカンダリメニュー効果を実現するためのJSの具体的なコードを参考までに共有していま...