vue 동적 컴포넌트 변경

박경준·2021년 12월 17일
0

신용점수

목록 보기
3/7

탭으로 페이지를 이동할때 동적으로 컴포넌트를 변경할 경우가 있다.
예를들어 url은 고정시키고 보여주는 화면만 변경하고 싶을때..

// 탭 이용하는 페이지
<template>
  <div style="margin-bottom: 300px">
    <ui-tab
      :tabs="tabs"
      v-model="selectedTab"
      propType="underline-dark"
      class="us-mt--10"
      @change="handleChangeTab"
    />
    <!-- 동적 컴포넌트 연결 -->
    <component :is="currentTabComponent" />
  </div>
</template>

<script>
export default {
  name: "credit-info-index",
  layout: "credit",
  created() {
    this.$parent.$emit("setTitle", "내 신용 정보");
  },
  data() {
    return {
      tabs: [
        { id: 0, title: "카드", name: "card" },
        { id: 1, title: "대출", name: "loan" },
        { id: 2, title: "연체", name: "overdue" },
        { id: 3, title: "보증", name: "surety" },
      ],
      selectedTab: 0,
      // 함수 형식으로 import 해온 컴포넌트를 data에 담아둔다.
      currentTabComponent: () => import("./card.vue"),
    };
  },

  computed: {
    tab() {
      return this.$route.query.tab;
    },
  },

  methods: {
    handleChangeTab(selectedTab) {
      // 동적 컴포넌트 변경
      this.currentTabComponent = () =>
        import(`./${this.tabs[selectedTab].name}.vue`);
      this.$router.replace({
        path: "/credit/info",
        query: { tab: this.tabs[selectedTab].name },
      });
    },
  },
  mounted() {
    // console.log(this.tab);
    if (this.tab) {
      this.selectedTab = this.tabs.find((t) => t.name === this.tab).id;
      this.currentTabComponent = () => import(`./${this.tab}.vue`);
    }
  },
};
</script>
// 탭 컴포넌트
<template>
  <div class="hb-tab" :class="{'hb-tab--dark': mode === 'dark'}">
    <div 
      v-for="(tab,index) in tabs" 
      :key="index"  
      :data-cy="`tab-${tab.id}`"
      class="hb-tab__each-wrapper"
    >
      <input
        type="radio"
        name="tab-group"
        :id="`hb-tab-${tab.id}`"
        @click="handleClickTab(tab.id)"
        :checked="selectedTab === tab.id"
        :disabled="tab.disabled"
      />
      <label
        :for="`hb-tab-${tab.id}`" 
        class="hb-tab__each"
        :class="`hb-tab__each--${propType} `"
      >
        {{tab.title}}
      </label>
    </div>
  </div>
</template>


<script>
export default {
  name: "hb-tab",
  // radio 버튼을 이용하기 때문에 v-model을 model 옵션을 이용해 표현해줘야 한다.
  model: {
    // 부모 컴포넌트에서 전달받은 selectedTab prop
    prop: "selectedTab",
    event: "change" // @change에서 쓰일 것으므로
  },
  props: {
    selectedTab: {
      type: [Number, String]
    },
    tabs: {
      type: Array,
      default: function() {
        return [];
      }
    },
    mode: {
      type: String,
      require: false
    },
    propType: {
      type: String,
      default: ""
    },
  },
  data() {
    return {};
  },
  methods: {
    handleClickTab(val) {
      this.$emit("change", val);
    }
  }
};
</script>
  • import 해온 컴포넌트를 data에 담아두는 것
  • v-model을 prop 형태로 이용하기 위해서는 model 옵션을 사용하는 것
    두가지에 핵심이 있다.
profile
빠굥

0개의 댓글