ホームページ  >  記事  >  ウェブフロントエンド  >  解決できない「動的マウント」の問題をVueを使って解決してみよう

解決できない「動的マウント」の問題をVueを使って解決してみよう

青灯夜游
青灯夜游転載
2022-09-02 20:30:552392ブラウズ

解決できない「動的マウント」の問題をVueを使って解決してみよう

一部の特殊なシナリオでは、コンポーネントを使用するタイミングが決定できない、または使用したいコンポーネントが Vue のテンプレート内で決定できない場合があります。この場合、コンポーネントを動的にマウントするか、ランタイム コンパイルを使用してコンポーネントを動的に作成してマウントする必要があります。

今日は、実際のプロジェクトから始めて、実際に顧客の問題を解決するときにコンポーネントを動的にマウントする方法を確認し、動的マウントの問題を解決する完全なプロセスを示します。

解決不可能な「動的マウント」

スプレッドシート コントロール SpreadJS が実行されているとき、次のような関数があります。セルをクリックすると、セルの内容を編集するための入力ボックスが表示されます。ユーザーは、カスタム セル タイプの仕様に従って入力ボックスのフォームをカスタマイズし、必要に応じてフォーム フォーム入力タイプを統合できます。

この入力ボックスの作成と破棄は、セル タイプの対応するメソッドを継承することによって実現されます。そのため、ここで問題が発生します。この動的作成メソッドは、VUE テンプレートで単純に構成して直接使用することはできません。 [関連する推奨事項: vuejs ビデオ チュートリアル ]

少し前に、お客様から次のような質問がありました。コントロールのカスタム セルは次のような Vue コンポーネントをサポートしていますか? ElementUIのオートコンプリート?

前述の問題のため:

# 長い間考えた後、私はお客様に真剣に答えました。「コンポーネントの運用ライフサイクルは、一貫性がないので使用できません」と言いましたが、彼は再び話題を変え、この問題は汎用コンポーネントを使用して解決できると言いました。

問題は正常に解決されました。

しかし、このどうしようもない「使えない」が、最近では真夜中の夢の中でも越えられないハードルにもなっている。

その後、ある日 Vue のドキュメントを見ていたら、App は実行中に #app にマウントされているのではないかと思いました。理論的には、他のコンポーネントも必要な Dom に動的にマウントできるはずなので、作成タイミングの問題は解決されます。

動的マウントを正式に有効にする

ドキュメントの表示を続けましょうグローバル APIVue.extend(options) は extend によって作成されます。 Vue インスタンスは、$mount メソッドを使用して DOM 要素に直接マウントできます。これはまさに必要なことです。

<div id="mount-point"></div>
 
// 创建构造器
var Profile = Vue.extend({
  template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
  data: function () {
    return {
      firstName: 'Walter',
      lastName: 'White',
      alias: 'Heisenberg'
    }
  }
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')

SpreadJS カスタム セルの例に従って AutoCompleteCellType を作成し、セルに設定します。

function AutoComplateCellType() {
}
AutoComplateCellType.prototype = new GC.Spread.Sheets.CellTypes.Base();
AutoComplateCellType.prototype.createEditorElement = function (context, cellWrapperElement) {
//   cellWrapperElement.setAttribute("gcUIElement", "gcEditingInput");
  cellWrapperElement.style.overflow = 'visible'
  let editorContext = document.createElement("div")
  editorContext.setAttribute("gcUIElement", "gcEditingInput");
  let editor = document.createElement("div");
  // 自定义单元格中editorContext作为容器,需要在创建一个child用于挂载,不能直接挂载到editorContext上
  editorContext.appendChild(editor);
  return editorContext;
}
AutoComplateCellType.prototype.activateEditor = function (editorContext, cellStyle, cellRect, context) {
    let width = cellRect.width > 180 ? cellRect.width : 180;
    if (editorContext) {
      // 创建构造器
      var Profile = Vue.extend({
        template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
        data: function () {
          return {
            firstName: 'Walter',
            lastName: 'White',
            alias: 'Heisenberg'
          }
        }
      })
      // 创建 Profile 实例,并挂载到一个元素上。
      new Profile().$mount(editorContext.firstChild);
    }
};

実行し、ダブルクリックして編集状態に入りますが、エラーが見つかりました

[Vue 警告]: テンプレート コンパイラが利用できない Vue のランタイム専用ビルドを使用しています。テンプレートをレンダリング関数にプリコンパイルするか、コンパイラに含まれるビルドを使用してください。

#エラー メッセージによると、現時点では 2 つの解決策があります。

  • runtimeCompiler をオンにし、runtimeCompiler: true 構成を vue.config.js に追加し、ランタイム コンパイルを許可します。 , そのため、動的コンポーネントのニーズを満たすためにテンプレートを動的に生成できます

  • # テンプレートを事前にコンパイルすることは動的にのみマウントされます。オートコンプリート コンポーネントは決定されます。この方法を使用できます
  • コンパイルされたコンポーネントをマウントできるように、動的マウント用に新しい AutoComplete.vue コンポーネントを作成します。
<template>
  <div>
    <p>{{ firstName }} {{ lastName }} aka {{ alias }}</p>
  </div>
</template>
<script>
export default {
  data: function () {
    return {
      firstName: "Walter",
      lastName: "White",
      alias: "Heisenberg",
    };
  },
};
</script>
 
 
import AutoComplate from './AutoComplate.vue'
 
 
AutoComplateCellType.prototype.activateEditor = function (editorContext, cellStyle, cellRect, context) {
    let width = cellRect.width > 180 ? cellRect.width : 180;
    if (editorContext) {
      // 创建构造器
      var Profile = Vue.extend(AutoComplate);
      // 创建 Profile 实例,并挂载到一个元素上。
      new Profile().$mount(editorContext.firstChild);
    }
};

ダブルクリックして編集状態に入り、コンポーネントの内容を確認します

次のステップでは、カスタム セルについても、次の設定を行う必要があります。コンポーネントContentの編集を取得し、コンポーネントにpropsを追加すると同時に、マウント時に作成されるVueComponentインスタンス上のすべてのpropsコンテンツを直接取得することで、対応する操作でデータ取得設定を実現できます。

AutoComplate.vue を更新し、プロパティを追加し、編集用の入力を追加します。

<template>
  <div>
    <p>{{ firstName }} {{ lastName }} aka {{ alias }}</p>
    <input type="text" v-model="value">
  </div>
</template>
<script>
export default {
  props:["value"],
  data: function () {
    return {
      firstName: "Walter",
      lastName: "White",
      alias: "Heisenberg",
    };
  },
};
</script>

this.vm を通じて VueComponent インスタンスを保存し、getEditorValue メソッドと setEditorValue メソッドで VUE コンポーネントの Value を取得して設定します。 。編集後、$destroy() メソッドを呼び出して、動的に作成されたコンポーネントを破棄します。

AutoComplateCellType.prototype.activateEditor = function (editorContext, cellStyle, cellRect, context) {
    let width = cellRect.width > 180 ? cellRect.width : 180;
    if (editorContext) {
      // 创建构造器
      var Profile = Vue.extend(MyInput);
      // 创建 Profile 实例,并挂载到一个元素上。
      this.vm = new Profile().$mount(editorContext.firstChild);
    }
};
 
AutoComplateCellType.prototype.getEditorValue = function (editorContext) {
    // 设置组件默认值
    if (this.vm) {
        return this.vm.value;
    }
};
AutoComplateCellType.prototype.setEditorValue = function (editorContext, value) {
    // 获取组件编辑后的值
    if (editorContext) {
      this.vm.value = value;
    }
};
AutoComplateCellType.prototype.deactivateEditor = function (editorContext, context) {
    // 销毁组件
    this.vm.$destroy();
    this.vm = undefined;
};

プロセス全体が実行されました。必要なのは、AutoComplate.vue で入力を ElementUI の el-autocomplete に置き換え、対応するメソッドを実装することだけです。

結果

効果を見てみましょう。

実際、動的マウントは複雑な操作ではありません。Vue の例を理解した後、vm を介してインスタンスを操作し、動的マウントやランタイム コンパイルされたコンポーネントを柔軟に使用することは難しくありません。

実は、すべての解決策は Vue チュートリアルの入門チュートリアルに記載されていますが、スキャフォールディングを使用したり、さまざまなツールを使用したりすることで、Vue の本来の目的が忘れられ、単純な問題がかえって複雑になってしまいます。

今日の共有はここで終了します。今後はさらに本格的で興味深いコンテンツをお届けします~

プログラミング関連の知識をさらに詳しく知りたい場合は、次のサイトをご覧ください: プログラミング入門! !

以上が解決できない「動的マウント」の問題をVueを使って解決してみようの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcnblogs.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。