>웹 프론트엔드 >View.js >vue3가 DefineAsyncComponent 및 구성 요소 태그를 사용하여 동적 렌더링 구성 요소를 구현하는 방법

vue3가 DefineAsyncComponent 및 구성 요소 태그를 사용하여 동적 렌더링 구성 요소를 구현하는 방법

王林
王林앞으로
2023-05-12 17:55:211376검색

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에 할당하는 것입니다. /code>는 레이블로 사용되거나 구성 요소의 is 속성에 할당될 수 있습니다. is 속성은 비즈니스 논리를 통해 동적으로 변경될 수 있습니다. 앞뒤로 렌더링 가능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、不能在组件的事件函数内挂载,

vue3가 DefineAsyncComponent 및 구성 요소 태그를 사용하여 동적 렌더링 구성 요소를 구현하는 방법

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

vue3가 DefineAsyncComponent 및 구성 요소 태그를 사용하여 동적 렌더링 구성 요소를 구현하는 방법

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

vue3가 DefineAsyncComponent 및 구성 요소 태그를 사용하여 동적 렌더링 구성 요소를 구현하는 방법

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

vue3가 DefineAsyncComponent 및 구성 요소 태그를 사용하여 동적 렌더링 구성 요소를 구현하는 방법

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. 복잡한 소개: 어떤 구성 요소를 소개할지 확실하지 않으며, 구성 요소의 경로는 백엔드에서 반환됩니다.

위 코드를 프로젝트 코드에 추가해도 소개가 작동하지 않습니다. 오류를 보고하면 참조는 항상 정의되지 않으며 동적 구성 요소 내의 open 함수를 호출할 수 없습니다. 수차례 시도한 결과 다음과 같은 결론을 내렸습니다

1. 처음에는 커스텀 컴포넌트를 마운트하고 버튼의 클릭 기능에서 ref 함수를 호출했는데 ref가 정의되지 않았습니다. 여러 번 시도해도 함수가 구현되지 않습니다(마운트하고 호출하기에 가장 적합한 위치입니다).

2. 그런 다음 구성 데이터를 초기화할 때(백엔드 SQL 쿼리) 구성요소를 axios의 then 함수에 마운트합니다. 를 클릭한 다음 ref의 함수가 호출되는 경우 ref는 여전히 null입니다.

3. 그런 다음 가장 바깥쪽 레이어에서 초기화 중에 마운트를 호출합니다. 즉, 수명 주기 함수 본문 내에서 테스트 결과는 여전히 동일합니다.
4. 그러다가 비동기 함수 본체 내 구성요소 장착을 완료할 수 없다는 것을 발견했습니다.

5. 비동기를 추가하지 않고 별도의 함수를 작성하고, 함수에 구성 요소를 마운트한 다음, 버튼의 참조에서 메서드를 호출하면 창이 성공적으로 나타납니다. 경로가 고정되어 있지 않고 백엔드 SQL이 결과를 다시 가져올 때까지 실행할 수 없기 때문에 이는 내가 원하는 것이 아닙니다. 🎜🎜요약: 위의 여러 테스트를 통해 다음과 같은 결론을 얻었습니다. 동적 구성 요소 참조 개체는 값을 가질 수 없습니다🎜1. 구성 요소의 이벤트 함수 🎜🎜vue3가 DefineAsyncComponent 및 구성 요소 태그를 사용하여 동적 렌더링 구성 요소를 구현하는 방법🎜🎜2. 마운트할 수 없습니다. axios🎜🎜의 then 함수 본문 vue3는 어떻게 정의AsyncComponent 및 구성 요소 태그를 사용하여 구현합니까? 동적 렌더링 구성 요소🎜🎜3. 비동기 선언이 있는 함수 본문에 마운트할 수 없습니다🎜🎜vue3과 함께 DefineAsyncComponent를 사용하는 방법 구성 요소 태그는 동적 렌더링 구성 요소를 구현합니다.🎜🎜4. vue🎜🎜vue3가 DefineAsyncComponent 및 구성 요소 태그를 사용하여 동적 렌더링 구성 요소를 구현하는 방법🎜🎜5. 가장 바깥쪽 레이어에만 마운트하고 구현할 수 있으며, 그러면 ref는 객체입니다. 🎜🎜다행히도 항상 다음과 같은 생각이 있습니다. 🎜페이지가 초기화되면 프로젝트에 전역적으로 마운트된 모든 뷰 구성 요소를 개체에 넣고 구성 요소 구성 요소를 사용합니다. 이때 백엔드는 구성 요소 경로를 제공할 필요가 없지만 개체에서 마운트된 구성 요소를 찾아 구성 요소 이름을 제공합니다. 에 반대합니다. 🎜const module = import.meta.glob('@/views/*/**.vue'); // 모든 프로젝트 경로 가져오기 🎜mudules는 뷰에 있는 모든 vue의 상대 경로이며, 그런 다음 이를 루프하고 루프 본문에 마운트한 다음 객체에 저장합니다. 키는 상대 경로의 프로젝트 이름입니다(아래에서 가로챌 수 있음). 🎜🎜🎜위의 아이디어를 바탕으로 반복적인 테스트와 구현을 통해 최종 기능을 구현했습니다. 🎜🎜
		} else if (action.modalCfg.type === &#39;CustomModal&#39;) {
  		// 这里的actionid和组件是对应的,所以在按钮触发后,通过按钮携带的actionid能取到对应的组件。
          componentKey.value = components[action.actionId];
          custom.value.init(row);
        }
🎜🎜버튼을 클릭하면 이벤트가 발생하고 어떤 구성 요소가 팝업 창에 나타날지 결정됩니다.🎜🎜rrreee🎜위 방법 이후: 어디에나 장착해도 오류가 보고되지 않으므로 완벽한 솔루션입니다. 🎜참고: ref를 마운트하고 사용하는 것은 동일한 메소드 본문에 있을 수 없습니다. 가능하면 페이지가 로드될 때 마운트가 수행되며 ref를 호출해야 할 때 오류가 보고되지 않습니다. 🎜

위 내용은 vue3가 DefineAsyncComponent 및 구성 요소 태그를 사용하여 동적 렌더링 구성 요소를 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제