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とネットワーク設定を接続する方法

推薦する

検証コード干渉を実装する js (静的)

この記事では、検証コード干渉を実装するためのjsの具体的なコードを参考までに共有します。具体的な内容...

mysql 行列変換サンプルコード

1. 需要3 つのテーブルがあります。一定期間にわたるさまざまな抗生物質感受性の結果、つまり rep...

HTML ブロックレベルタグとインラインタグの違い

1. ブロックレベル要素: 独立して存在できる能力を指します。通常、ブロックレベル要素は改行によって...

JavaScript配列の一般的なメソッドの例のまとめ

目次一般的な配列メソッドconcat() メソッドjoin() メソッドpop() メソッドpush...

Vue で SuperMap を使用する練習

目次序文関連資料Vue プロジェクトが 2 次元ハイパーグラフを導入ハイパーグラフ 2D ケース引用...

resizeを使用して画像切り替えプレビュー機能を実装する方法

要点CSS resize プロパティを使用すると、要素のサイズ変更可能性を制御できます。サイズ変更を...

forループ内のvarの問題の解決

序文var は ES5 における変数宣言方法です。var で変数を宣言するとループ変数がグローバル変...

this.parentNode.parentNode (親ノードの親ノード) はどういう意味ですか?

親ノードの親ノード、例えば、このような段落がありますHTML:コードをコピーコードは次のとおりです。...

MySQL の起動時に InnoDB エンジンが無効になる問題の解決方法

問題を見つける今日、仕事中に、ローカル データベースから仮想マシン CentOS 6.6 上のデータ...

VS2019 が mysql8.0 データベースに接続する方法 (画像とテキスト付き)

1. まず、VS2019とMySQLデータベースを準備します。どちらも公式サイトからダウンロードで...

バージョン管理ツール Rational ClearCase の紹介

Rational ClearCase は、コードやその他のソフトウェア開発資産のバージョン管理を実...

画像を使用してハイパーリンクのパーソナライズされた下線を実現します

画像内に下線付きのリンクが表示されても驚かないでください。実はとても簡単なので、あなたにもできるので...

Dockerネットワーク作成に--subnetを追加した後の問題を解決する

Docker ネットワークの作成に –subnet を追加した後、docker network ls...

Docker 学習: コンテナ コンテナの具体的な使用方法

コンテナは Docker のもう一つの中心的な概念です。簡単に言えば、コンテナとは、独立して実行され...

モバイルアダプティブスタイルで@mediaを使用する方法

一般的な携帯電話のスタイル: @media all および (orientation : 縦向き) ...