익명의 개발노트

[vue.js] 공통부분 컴포넌트 처리 & Slot & slot-scope 본문

코딩일기/TIL

[vue.js] 공통부분 컴포넌트 처리 & Slot & slot-scope

캡틴.JS 2019. 12. 24. 15:26
반응형

1. 보여지는 화면의 구성이 같고, 보여지는 데이터가 다른 경우

  1) 공통 컴포넌트 하나 생성 후  API콜 부분 분기처리

  2) 템플릿 부분  v-if문으로 보여지는 화면 분기처리

      (1) <template> 를 사용하여 분기처리해도 되고, 바로 태그에 v-if 달아서 분기처리 해도 됨.

  3) 데이터 받아와서 저장하는 부분 분기처리

2. 부모컴포넌트에서 하위 컴포넌트 데이터 전달시 

   1) props이용하거나, 자식에서 데이터 생성 => props로 데이터 내려주는 게 드라이한 설계

 

3. Slot을 이용하여 표시

   1) react의 children같은 기능, 1번같이 데이터가 일부 다른데 수정하기 애매한 경우 Slot으로 써도 되고

       애초에 Slot을 이용해도 좋음.

   2) 하위 컴포넌트에 화면 받아서 보여주고 싶은 부분을 slot으로 선언하고 name 을 지정

      * slot 네임으로 사용시에는 보여주고자하는 컴포넌트 내부에서 별도 영역을 정해주고 사용해야한다. 

//자식컴포넌트

<template>
  <div class="user-container">
    <div>User</div>
    <div class="user-description">
      <slot name="username">
        <!-- 상위컴포넌트에서 정의할 영역 -->
      </slot>
    </div>
  </div>
</template>

   3) 상위 컴포넌트에서 태그나, 데이터를 보내주면 된다.

//상위 컴포넌트
<user-profile :info="fetchedItem">
  <div slot="username">{{fetchedItem.user}}</div>
</user-profile>

   * 아래와 같이 작성하면 안나온다.

//상위 컴포넌트
<user-profile slot="username" :info="fetchedItem">
  <div>{{fetchedItem.user}}</div>
</user-profile>

   4) name 지정없이도 가능함.

 

4. Controlled Component 방식(input 박스를 활용한 checkbox구현)

   1) 컴포넌트를 세부적으로 쪼개야 할때, 데이터를 아래로 전달하는 방식인 Props와  아래서 위로 올리는 방식인 Emit을

      활용한다.

   2) check box를 예를 들면, 체크값을 Props로 하위 컴포넌트에 전달시 하위에서 바로 변경하면 에러가 발생한다.

       하위 컴포넌트에서 클릭하여 변경된 값을 상위 컴포넌트로 올릴때 emit으로 값만 지정해 주고 올리기만 하면

       에러없이 처리 가능하다.

      * 이때, emit의 첫번째 인자로 들어가는 값을 값을 input으로 맞춰줘야한다. 

//app.vue

<template>
  <check-box v-model="checked"></check-box>
</template>

<script>
import CheckBox from './components/CheckBox.vue';

export default {
  components: {
    CheckBox
  },
  data(){
    return{
       checked: false
    }
  },
  
}
</script>
//Checkbox.vue

<template>
  <input type="checkbox" :value="value" @click="toggleCheckBox"/>
</template>

<script>
export default {
  //v-model
  //@input 이벤트
  //:value 값 
  props: ['value'], //false
  methods:{
    toggleCheckBox(){
      this.$emit('input',!this.value)
    }
  }
}
</script>

5. slot-scope를 이용하여 컴포넌트를 더 잘게 쪼갤 수도 있다. 

   1) View없이 데이터로 이루어진 컴포넌트의 값을 상위 컴포넌트로 emit이 아닌 Slot-scope를 이용하여 표현

   2) app.vue에서 slot-scope의 값을 명시하기 위해서는 자식 컴포넌트인 fetchData.vue에서 Slot-scope를

       명시해주어야 함.

//app.vue

<template>
  <div>
    <fetch-data url="https://jsonplaceholder.typicode.com/users/1">
      <!-- ... -->
      <div slot-scope="{response, loading}">
        <div v-if="!loading">
          <p>name : {{response.name}}</p>
          <p>email : {{response.email}}</p>
        </div>
        <div v-if="loading">loading...</div>
      </div>
      
    </fetch-data>
  </div>
</template>

<script>
import FetchData from './components/FetchData.vue'

export default {
  components: {
    FetchData
  },
}
</script>
//fetchData

<script>
import axios from 'axios';

export default {
  props: ['url'],
  data() {
    return {
      response: null,
      loading: true,
    }
  },
  created() {
    axios.get(this.url)
      .then(response => {
        this.response = response.data;
        this.loading = false;
      })
      .catch(error => {
        alert('[ERROR] fetching the data', error);
        console.log(error);
      });
  },
  //아래와 같이 명시해 주어야 상위 컴포넌트에서 slot-scope를 사용할 수 있다.
  render() {
    return this.$scopedSlots.default({
      response: this.response,
      loading: this.loading,
    });
  },
}
</script>
반응형
Comments