blog

vue3-로컬 컴포넌트/글로벌 컴포넌트/재귀 컴포넌트/동적 컴포넌트

로컬 컴포넌트 직접 도입 방식 글로벌 컴포넌트 프로젝트의 main.ts를 찾아 컴포넌트 도입 앱 인스턴스에 마운트 재귀 컴포넌트 컴포넌트 A에서 컴포넌트 A를 재귀적으로 사용, 불...

Oct 17, 2025 · 5 min. read
シェア

로컬 컴포넌트

방법 직접 소개
<template>
 <div>
 <test ref="TestRef" />
 </div>
</template>
<script setup lang="ts">
import Test from './test.vue';
</script>
<style scoped></style>

글로벌 컴포넌트

  • 프로젝트의 main.ts를 찾아 컴포넌트를 소개합니다.
  • 앱 인스턴스에 마운트
import { createApp } from 'vue'; import App from './App.vue'; import Test from '@/pages/apply-device/order-aws/test.vue'; const app = createApp(App); // 첫 번째 매개변수인 사용자 정의 이름은 대문자 혹의 첫 글자이어야 하며 다음 두 단어를 포함해야 합니다. // 두 번째 매개변수: 컴포넌트를 전역적으로 등록해야 할 필요성 app.component('TestDiv', Test); app.mount('#app');

재귀 컴포넌트

  • 컴포넌트 이름을 직접 사용하여 컴포넌트 A를 가져오지 않고 컴포넌트 A 내에서 재귀적으로 사용합니다.
  • 내보내기 기본값을 사용하여 별칭을 만든 다음 별칭을 사용합니다.
  • 플러그인을 구성한 다음 플러그인에서 제공하는 defineOptions 메서드를 호출하여 별칭을 등록해야 하는 unplugin-vue-define-options 플러그인을 사용합니다.
부모 컴포넌트
<template>
 <div>
 <test :data="data" />
 </div>
</template>
<script lang="ts">
export default {
 name: 'ApplyAWSIndex',
};
</script>
<script setup lang="ts">
import { reactive } from 'vue';
import Test from './test.vue';
interface TreeApi {
 name: string;
 checked: boolean;
 children?: TreeApi[];
}
const data = reactive<TreeApi[]>([
 {
 name: '1',
 checked: false,
 children: [
 {
 name: '1-1',
 checked: false,
 },
 ],
 },
 {
 name: '2',
 checked: false,
 },
 {
 name: '3',
 checked: false,
 children: [
 {
 name: '3-1',
 checked: false,
 children: [
 {
 name: '3-1-1',
 checked: false,
 },
 ],
 },
 ],
 },
]);
</script>
<style scoped></style>
재귀 컴포넌트

파일 이름: test.Vue

<template>
 <div v-for="item in data" :key="item.name" style="margin-left: 10px" @click.stop="onClick(item, $event)">
 <input v-model="item.checked" type="checkbox" /><span>{{ item.name }}</span>
 
 <!-- 방법 1>
 <test v-if="item?.children?.length" :data="item.children" />
 
 <!-- 두 번째 방법>
 <!-- <OtherName v-if="item?.children?.length" :data="item.children" />-->
 
 </div>
</template>
<script lang="ts">
// 2번 방법 별칭 정의
export default {
 name: 'OtherName',
};
</script>
<script setup lang="ts">
interface TreeApi {
 name: string;
 checked: boolean;
 children?: TreeApi[];
}
withDefaults(defineProps<{ data?: TreeApi[] }>(), { data: undefined });
const onClick = (item, e) => {
 console.log(item);
 console.log(e);
};
</script>
<style scoped></style>

동적 컴포넌트

  • 선택 항목에 따라 해당 컴포넌트를 자동으로 렌더링합니다.
방법 1
  • 성능 향상
  • 컴포넌트 객체를 래핑하기 위해 shallRef 및 markRaw 메서드를 사용하는 것에 유의하세요.
<template>
 <div>
 <div style="display: flex">
 <div v-for="item in data" :key="item.name" style="border: 2px solid black; margin-right: 2px">
 <a @click="choice = item.comp">{{ item.name }}</a>
 </div>
 </div>
 <component :is="choice" />
 </div>
</template>
<script lang="ts">
export default {
 name: 'ApplyAWSIndex',
};
</script>
<script setup lang="ts">
import { markRaw, reactive, shallowRef } from 'vue';
import AVue from './A.vue';
import BVue from './B.vue';
import CVue from './C.vue';
const choice = shallowRef(AVue);
const data = reactive([
 {
 name: 'A ,
 comp: markRaw(AVue),
 },
 {
 name: 'B ,
 comp: markRaw(BVue),
 },
 {
 name: 'C ,
 comp: markRaw(CVue),
 },
]);
</script>
<style scoped></style>
주의해야 할 모드 I 문제
  • ref 응답 범위를 제어해야 합니다. 이 오류는 컴포넌트를 반응형 변수로 만들면 컴포넌트 내의 많은 속성/정보가 도용되어 불필요한 성능 낭비를 초래하므로 피해야 합니다. 응답 범위를 제어하려면 컴포넌트를 'markRaw' 또는 'allowRef' 메서드를 통해 래핑하세요.
[Vue warn]: Vue received a Component which was made a reactive object. 
This can lead to unnecessary performance overhead,
and should be avoided by marking the component with `markRaw` 
or using `shallowRef` instead of `ref`. 
Component that was made reactive: 
방법 2
  • 문자열 메서드, 성능은 메서드 1보다 낮습니다.
  • 차이점은 정의된 컴포넌트의 위치에 있으며, 좋은 매핑 관계를 만들기 위해 내보내기 기본값을 통해 미리 선언해야 합니다.
  • 이 시점에서는 markRaw, shallowRef 메서드가 필요하지 않습니다.
<template>
 <div>
 <div style="display: flex">
 <div v-for="item in data" :key="item.name" style="border: 2px solid black; margin-right: 2px">
 <a @click="choice = item.comp">{{ item.name }}</a>
 </div>
 </div>
 <component :is="choice" />
 </div>
</template>
<script lang="ts">
import AVue from './A.vue';
import BVue from './B.vue';
import CVue from './C.vue';
export default {
 name: 'ApplyAWSIndex',
 components: { AVue, BVue, CVue },
};
</script>
<script setup lang="ts">
import { reactive, ref } from 'vue';
const choice = ref('AVue');
const data = reactive([
 {
 name: 'A ,
 comp: 'AVue',
 },
 {
 name: 'B ,
 comp: 'BVue',
 },
 {
 name: 'C ,
 comp: 'CVue',
 },
]);
</script>
<style scoped></style>
AB, B, C 컴포넌트 내용
// <template> <div style="border: 1px solid black; height: 500px">A</div> </template> <script setup lang="ts"></script> <style scoped></style> // <template> <div style="border: 1px solid black; height: 500px">B</div> </template> <script setup lang="ts"></script> <style scoped></style> // <template> <div style="border: 1px solid black; height: 500px">C</div> </template> <script setup lang="ts"></script> <style scoped></style>
Read next

WSL 외부 ext4 USB 레코드 마운트하기

디스크 식별 WSL 2에서 마운트할 파티션을 나열하고 선택합니다.\nPS GET- -query "SELECT * from "\n

Oct 16, 2025 · 1 min read