Maison  >  Article  >  interface Web  >  Comment vue3 utilise finishAsyncComponent et les balises de composants pour implémenter des composants de rendu dynamique

Comment vue3 utilise finishAsyncComponent et les balises de composants pour implémenter des composants de rendu dynamique

王林
王林avant
2023-05-12 17:55:211326parcourir

1. Introduction dynamique de base des composants :

Une introduction dynamique simple signifie que le front-end sait quels composants introduire et introduit plusieurs composants dans le composant parent, mais ne le restitue pas une fois que certaines conditions sont remplies. un certain composant Rend le composant spécifié à une position.

<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>

L'exemple ci-dessus consiste à implémenter le composant de montage via defineAsyncComponent de vue et à l'attribuer à customModal. Vous pouvez utiliser <custom-modal> est utilisé comme étiquette, ou il peut être attribué à l'attribut is dans le composant. L'attribut is pointe vers une variable. La valeur de la variable peut être modifiée dynamiquement via la logique métier, de sorte que plusieurs composants. peut être rendu dans les deux sens<code>defineAsyncComponent实现挂载组件,并赋值给customModal ,模板中可以直接使用<custom-modal></custom-modal>作为标签使用,也可以将它赋值给component中的is属性,is属性执向一个变量,可通过业务逻辑动态,更改该变量的值,就可以实现多个组件进行来回的渲染了

<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

二、复杂的引入:不确定到底引入什么组件,组件的路径由后端返回

将以上代码 添加到项目代码中,并不能实现,虽然引入不报错,但是ref一直为undefined,无法调用动态组件内的open函数。
不断尝试了很多次,得出以下结论

1.起初是在按钮的click函数内去挂载自定义组件并调用ref函数的,ref为undefined。
尝试多次不能实现功能(这里是挂载与调用最合适的位置),
2.接着又在初始化配置数据时(查询后端sql),axios的then函数内挂载组件,然后点击按钮的地方调用ref内的函数,ref依旧为null。
3. 接着在最外层,调用初始化时挂载,也就是生命周期函数体内,测试还是一样的结果。
4. 接着发现带有async函数体内挂载组件,也无法完成。
5.单独写个函数,不加async,函数内挂载组件,然后再生命周期外调用该函数,按钮内调用ref内的方法,成功弹窗。这并不是我想要的,因为路径不是固定的,它要等到后端sql放回结果,才能执行。

总结:上面的多次测试,得出以下结论,都不能让动态组件ref对象有值
1、不能在组件的事件函数内挂载,

Comment vue3 utilise finishAsyncComponent et les balises de composants pour implémenter des composants de rendu dynamique

2、不能在axios的then函数体内挂载

Comment vue3 utilise finishAsyncComponent et les balises de composants pour implémenter des composants de rendu dynamique

3、不能在带有async声明的函数体内挂载

Comment vue3 utilise finishAsyncComponent et les balises de composants pour implémenter des composants de rendu dynamique

4、不能在vue的生命周期内挂载

Comment vue3 utilise finishAsyncComponent et les balises de composants pour implémenter des composants de rendu dynamique

5、只能在最外层挂载实现,这时ref才是个对象。

好在天无绝人之路;脑海里有个思路:
页面初始化时将项目里所有的全局挂载view组件扔到一个object内,使用component组件,is:对应object内指定的组件对象,然后通过后端的数据,这时后端就不用给组件路径了,给个组件名,我从object中找到挂载的组件然后将对象给is。
const modules = import.meta.glob('@/views/*/**.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>

2. Introduction complexe : vous ne savez pas quel composant introduire, le chemin du composant est renvoyé par le backend

L'ajout du code ci-dessus au code du projet ne fonctionne pas bien que l'introduction ne fonctionne pas. signaler une erreur, la référence est toujours indéfinie et ne peut pas être appelée. La fonction open dans le composant dynamique. Après avoir essayé plusieurs fois, nous sommes arrivés aux conclusions suivantes

1 Au début, nous avons monté le composant personnalisé et appelé la fonction ref dans la fonction de clic du bouton, et la référence n'était pas définie. La fonction ne peut pas être réalisée après plusieurs tentatives (c'est l'endroit le plus approprié pour monter et appeler),

2 Ensuite, lors de l'initialisation des données de configuration (interrogation du SQL back-end), montez le composant dans la fonction then d'axios. , puis cliquez sur le bouton Là où la fonction dans ref est appelée, ref est toujours nulle.

3. Ensuite, dans la couche la plus externe, appelez le support lors de l'initialisation, c'est-à-dire que dans le corps de la fonction de cycle de vie, les résultats des tests sont toujours les mêmes.
4. Ensuite, j'ai découvert que le montage des composants dans le corps de la fonction asynchrone ne pouvait pas être terminé.

5. Écrivez une fonction distincte sans ajouter d'async, montez le composant dans la fonction, puis appelez la fonction en dehors du cycle de vie. Appelez la méthode dans la référence dans le bouton et la fenêtre apparaîtra avec succès. Ce n'est pas ce que je veux car le chemin n'est pas fixe et il ne peut pas être exécuté tant que le backend SQL n'a pas renvoyé les résultats. 🎜🎜Résumé : Les multiples tests ci-dessus ont conduit aux conclusions suivantes : l'objet ref du composant dynamique ne peut pas avoir de valeur🎜1. Il ne peut pas être monté dans la fonction événementielle du composant, 🎜🎜Comment vue3 utilise finishAsyncComponent et les balises de composant pour implémenter les composants de rendu dynamique🎜🎜2. Il ne peut pas être monté dans le corps de la fonction then d'axios🎜🎜 Comment vue3 utilise-t-il finishAsyncComponent et les balises de composants pour implémenter composants de rendu dynamique🎜🎜3. Ne peut pas être monté dans un corps de fonction avec une déclaration asynchrone🎜🎜Comment utiliser finishAsyncComponent avec vue3 La balise composant implémente des composants de rendu dynamique🎜🎜4. Elle ne peut pas être montée pendant le cycle de vie de vue🎜🎜Comment vue3 utilise finishAsyncComponent et les balises de composants pour implémenter des composants de rendu dynamique🎜🎜5. Il ne peut être monté que sur la couche la plus externe, puis ref est un objet. 🎜🎜Heureusement, il y a toujours un moyen ; j'ai une idée en tête : 🎜Lorsque la page est initialisée, jetez tous les composants de vue montés globalement dans le projet dans un objet, utilisez le composant, c'est : correspond au composant objet spécifié dans l'objet, puis transmets les données du back-end à ce stade, le back-end n'a pas besoin de donner le chemin du composant, mais donne un nom de composant. Je trouve le composant monté à partir de l'objet, puis je donne le. s'opposer à est. 🎜const modules = import.meta.glob('@/views/*/**.vue'); // Récupère tous les chemins du projet 🎜mudules est le chemin relatif de toutes les vues dans les vues, et puis bouclez-le, montez-le dans le corps de la boucle et stockez-le dans un objet. La clé est le nom du projet du chemin relatif (vous pouvez l'intercepter ci-dessous). 🎜🎜🎜Avec les idées ci-dessus, grâce à des tests et une mise en œuvre répétés, la fonction finale a été réalisée. 🎜🎜
		} else if (action.modalCfg.type === &#39;CustomModal&#39;) {
  		// 这里的actionid和组件是对应的,所以在按钮触发后,通过按钮携带的actionid能取到对应的组件。
          componentKey.value = components[action.actionId];
          custom.value.init(row);
        }
🎜🎜Cliquez sur le bouton pour déclencher l'événement et déterminer quel composant apparaîtra dans la fenêtre pop-up🎜🎜rrreee🎜Après la méthode ci-dessus : aucune erreur ne sera signalée lors du montage n'importe où, ce qui est une solution parfaite. 🎜Remarque : le montage et l'utilisation de ref ne peuvent pas être dans le même corps de méthode. Si possible, lorsque la page est chargée, le montage est effectué et aucune erreur ne sera signalée lorsque ref doit être appelé. 🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer