ホームページ  >  記事  >  ウェブフロントエンド  >  vue3 がどのようにdefineAsyncComponent タグとコンポーネント タグを使用して動的レンダリング コンポーネントを実装するか

vue3 がどのようにdefineAsyncComponent タグとコンポーネント タグを使用して動的レンダリング コンポーネントを実装するか

王林
王林転載
2023-05-12 17:55:211328ブラウズ

1. コンポーネントの基本的な動的導入:

単純な動的導入とは、フロントエンドがどのコンポーネントを導入するかを認識し、複数のコンポーネントを親コンポーネントに導入しますが、レンダリングはせず、特定の条件を満たすことを意味します。 、指定されたコンポーネントを特定の場所にレンダリングします。

<template>
	 <custom-modal ref="custom"></custom-modal>
</template>
<script>
 import {
    reactive,
    ref,
    shallowReactive,
    onActivated,
    defineAsyncComponent,
  } from &#39;vue&#39;;
 const customModal = defineAsyncComponent(() => import(&#39;./modal/CustomModal.vue&#39;));
 const custom = ref();
 </script>

上記の例は、vue の defineAsyncComponent を通じてマウント コンポーネントを実装し、それを customModal に割り当てます。<custom-modal> はタグとして使用されるか、コンポーネントの is 属性に割り当てられます。is 属性は変数を指します。変数の値はビジネス ロジックを通じて動的に変更でき、複数のコンポーネントで変更できます。 </custom-modal>

<template>
<component :is="componentKey" ref="custom"></component>
</template>
 import {
    reactive,
    ref,
    shallowReactive,
    onActivated,
    defineAsyncComponent,
  } from &#39;vue&#39;;
 const componentKey = ref(null);
 const components: any = shallowReactive({});
 const customModal = defineAsyncComponent(() => import(&#39;./modal/CustomModal.vue&#39;));
 componentKey  = customModal

2. 複雑な導入: どのコンポーネントを導入すればよいかわからない、コンポーネントのパスがバックエンドによって返される

上記のコードをプロジェクト コードに追加することはできません。導入部ではエラーは報告されませんが、 ref は常に未定義であり、動的コンポーネントの open 関数を呼び出すことはできません。
何度も試した結果、次の結論に達しました

1. まず、カスタム コンポーネントをマウントし、ボタンのクリック関数で ref 関数を呼び出します。 ref が未定義でした。
何度試しても機能が実現できない(マウントと呼び出しに最適な場所です)
2. その後、構成データの初期化(バックエンドSQLへのクエリ)時にコンポーネントがマウントされます。 axios の then 関数、その後、ボタンがクリックされた場所で ref の関数が呼び出されますが、ref はまだ null です。
3. 次に、最外層で、初期化中にマウントを呼び出します (つまり、ライフサイクル関数本体内で) テスト結果は同じです。
4. すると、async 関数本体内のコンポーネントのマウントが完了できないことがわかりました。
5. async を追加せずに別の関数を作成し、関数内でコンポーネントをマウントし、ライフサイクルの外で関数を呼び出すと、ボタンの ref 内のメソッドを呼び出すと、ウィンドウが正常にポップアップします。パスが固定されておらず、バックエンド SQL が結果を戻すまで実行できないため、これは私が望むものではありません。

要約: 上記の複数のテストにより、次の結論が得られました: 動的コンポーネント ref オブジェクトに値を持つことは許可されません
1。コンポーネントのイベント関数内にマウントすることはできません

vue3 がどのようにdefineAsyncComponent タグとコンポーネント タグを使用して動的レンダリング コンポーネントを実装するか

2. axios の then 関数本体にはマウントできません

vue3 がどのようにdefineAsyncComponent タグとコンポーネント タグを使用して動的レンダリング コンポーネントを実装するか

##3. 関数本体にはマウントできませんasync 宣言

vue3 がどのようにdefineAsyncComponent タグとコンポーネント タグを使用して動的レンダリング コンポーネントを実装するか

4. vue のライフサイクル中はマウントできません。

vue3 がどのようにdefineAsyncComponent タグとコンポーネント タグを使用して動的レンダリング コンポーネントを実装するか

5. のみ可能です。最外層に実装することになりますが、このときrefはオブジェクトとなります。

幸いなことに、確実なパスはありませんが、私の頭の中にアイデアがあります:

ページが初期化されたら、プロジェクト内でグローバルにマウントされたすべてのビュー コンポーネントをオブジェクトにスローし、そのコンポーネント コンポーネントを使用します。 is: 対応する オブジェクトで指定されたコンポーネントオブジェクトはバックエンドデータを介して渡されます このとき、バックエンドはコンポーネントのパスを与える必要はありませんが、コンポーネント名を与えます オブジェクトからマウントされたコンポーネントを見つけて、の対象です。

const modules = import.meta.glob('@/views/*/**.vue'); // すべてのプロジェクト パスを取得します mudules はビュー パス内のすべての vue に相対的ですをループし、ループ本体でマウントを実装し、オブジェクトに格納します。キーは相対パスのプロジェクト名です (以下でインターセプトできます)。

上記のアイデアのもと、テストと実装を繰り返し、最終的な機能を実現しました。

<template>
<component :is="componentKey" ref="custom"></component>
</template>
<script>
 import {
    reactive,
    ref,
    shallowReactive,
    onActivated,
    defineAsyncComponent,
  } from &#39;vue&#39;;
	
	//声明componentkey,用于告诉component当前挂载什么组件,components为一个对象,存放多个不确定的自定义组件。
  const componentKey = ref(null);
  const components: any = shallowReactive({});

  // 组件挂载
  const initTableConfig = (gridId, type) => { 
   queryTableConfig({ gridId }).then(({ data }) => {
      if (type === &#39;main&#39;) {
        Object.assign(mainConfig, data);
        tabsKey.value = -1;
      } else {
        tabsDetail.value.push(data);
        tabsKey.value = tabsDetail.value.length - 1;
      }
      // 涉及到自定义组件的部分,这里需要提前挂载,在用到时不至于ref为null
      XEUtils.objectEach(data.action, (action, key) => {
        if (
          action.modalCfg &&
          action.modalCfg.type === &#39;CustomModal&#39; &&
          action.modalCfg.src
        ) {
          components[action.actionId] = defineAsyncComponent(
            () => import(`../../../${action.modalCfg.src}`)
          );
          //注意:这里的路径后端只能返回相对路径,不能使用@/xxx/xxx.vue ,不能使用src/xxx/xxx.vue,只能./xxx.vue或者../../xxx/xxx.vue。由于并不确定组件在什么位置,避免容易出错的原则,我在前端通过../../../的形式将路径回退到src下,后端只需要从src下配置路径即可,不用考虑那么多了。如后端src的值为src/xxx/xxx/xxx.vue 则在前端合成的路径就为../../../src/xx/xxx/xxx.vue
          componentKey.value = components[action.actionId];
          // 为什么componentKey.vue在这里赋值,在后面点击窗口后又赋值,这里能不能省略。
		//	答:这里省略的话,到点击按钮触发时会报错,第一次点击会报错,第二次点击不会报错,窗口正常弹出。可能是因为,组件挂载时并没有引入组件,只在使用时才引入,如果上面不提前将挂载好的组件引入进来,后面触发事件触发时引入在调用ref,执行太快,costom就会报错,所以才会点两次才弹窗。
        }
      });
    });
  };
 </script>

ボタンをクリックしてイベントをトリガーし、ポップアップ ウィンドウにどのコンポーネントがポップアップするかを決定します

		} else if (action.modalCfg.type === &#39;CustomModal&#39;) {
  		// 这里的actionid和组件是对应的,所以在按钮触发后,通过按钮携带的actionid能取到对应的组件。
          componentKey.value = components[action.actionId];
          custom.value.init(row);
        }

上記の方法を実行した後: エラーは発生しませんどこにでも取り付けた場合に報告されます。完璧なソリューションです。

注: ref のマウントと使用を同じメソッド本体内で行うことはできません。可能であれば、ページがロードされるときにマウントが実行され、ref を呼び出す必要があるときにエラーは報告されません。

以上がvue3 がどのようにdefineAsyncComponent タグとコンポーネント タグを使用して動的レンダリング コンポーネントを実装するかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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