본문 바로가기

front-end 국비과정 학습일지

front-end 국비과정 일차 36일차 학습일지 Vue:props,v-slot,emit,(provide,inject),ref

컴포넌트 장점 
재활용이 가능하다.

props: 부모컴포넌트에서 자식 컴포넌트에게 데이터를 전달하는 기능을 한다
props는부모 자식 간의 데이터 통신이라고도 부른다

props 활용법
1부모 컴포넌트에서 속성과 값을 정의한다
2자식 컴포넌트에 script에서 props를 정의한다 
3props안에 부모컴포넌트에서 사용된 속성이름을 정의한다. 데이터 타입과, 기본값을 설정 할 수 있다 
4 부모 컴포넌트에서 전달할 데이터가 문자열이 아닌 경우 자식컴포넌트에 props에 데이터를 전달하기위해선 v-bind를 사용해야한다


ex)

//부모 컴포넌트 
<template>
  <MyBtn />
  <MyBtn size="100px" />
  <MyBtn />
  <MyBtn />
</template>

<script>
import MyBtn from "./components/MyBtn.vue";

export default {
  components: {
    MyBtn,
  },
};
</script>

//자식 컴포넌트
<template>
  <p :style="{ fontSize: size }">props 활용 예시</p>
</template>

<script>
export default {
  props: {
    size: {
      type: String,
      default: "16px",
    },
  },
};
</script>

 



루트란?
최상위 요소라는 것을 의미한다
template영역에 자식요소를 루트라고 부른다

상속이란?
부모컴포넌트에서 작성한 속성이 자식 컴포넌트에 전파되는것을 상속이라한다.
상속은 자식 컴포넌트의 루트가 하나일때만 일어나는 현상이다 즉 template의 자식요소가 2개이상이면 상속은 일어나지않는다
자식 컴포넌트의 script영역에서 inheritAttrs라는속성을 false로 명시하면 상속은 일어나지 않는다

ex)

//부모컴포넌트
<template>
  <MyBtn 
    class="test"
    style="color:red">
     Banana 
  </MyBtn>
</template>

<script>
import MyBtn from "./components/MyBtn.vue";

export default {
  components: {
    MyBtn,
  }
};
</script>

//자식 컴포넌트
<template>
  <div class="btn">
    <slot></slot>
  </div>
</template>

<script>
export default {
  inheritAttrs:false,
};
</script>

<style scoped>
.btn {
  display: inline-block;
  margin: 4px;
  padding: 6px 12px;
  border-radius: 4px;
  background-color: gray;
  color: white;
  cursor: pointer;
}
</style>





slot:
1부모 컴포넌트에서 자식 컴포넌트에 요소를 지정한다 
즉 자식 컴포넌트에서 slot을 사용하면 부모컴포넌트에서 작성된 모든 요소를 복사하여 slot의 담아낸다.
2만약 부모 컴포넌트에서 작성된 내용이 없다면 자식 컴포넌트에서 slot에서 기본값으로 출력할 text를 작성 할 수 있는데 어려운 말로 FallbackContent라고한다

ex)

//부모 컴포넌트
<template>
  <Child>
    <p>자식 컴포넌트에서 slot 을 사용하면</p>
    <p>부모 컴포넌트에서 작성된 요소들을 모두 복사 한다는 것을</p>
    <h2>증명!</h2>
  </Child>
</template>

<script>
import Child from "./components/Child.vue";
export default {
  components: {
    Child,
  },
};
</script>

//자식 컴포넌트 
<template>
  <slot>부모 컴포넌트에서 작성된 내용이 없을때 출력 하는 text1</slot>
  <slot>부모 컴포넌트에서 작성된 내용이 없을때 출력 하는 text2</slot>
</template>

<script>
export default {};
</script>

 



v-slot:
1 slot에 이름(name)을 부여하여 원하는 순서대로 출력 할 수 있게 만드는 기능을 한다 
2 부모 컴포넌트에서 template라는 영역을 만든후 v-slot을 명시하고, template안에서 요소를 작성한다 
이때 v-slot은 자식 컴포넌트에 slot과 연결되는데 아무거나 연결 할 수 없기때문에 이름을 지정 해 준다 
3 자식 컴포넌트는 slot에 name이라는 속성을 통해 v-slot에 이름을 참조하여 부모 컴포넌트에 v-slot이 명시된 template안에 요소들을 slot안에 담는다
4 v-slot은 약어로 #이라는 기호를 사용해 대체 할 수 있다
ex)
//부모컴포넌트

<template>
  <Child>
    <template v-slot:test1>
      <p>v-slot은 이름을 가진 slot 이다</p>
      <p>자식 컴포넌트에 slot안에 name속성과 부모컴포넌트의 v-slot에 이름을 연결한다</p>
      <p>연결되면 해당 이름을 가진 template안에 요소들이 출력된다</p>
      <h2>증명!</h2>
    </template>

    <template #test2>
      <p>v-slot은 #이라는 기호로 대체 할 수 있다</p>
      <p>참고로 v-bind = :, v-on=@ v-slot = # 으로 대체된다^^</p>
      <p>
        자식 컴포넌트에는 동일하게 slot안에 name속성을 사용해 부모 컴포넌트의 v-slot이름과
        연결한다
      </p>
      <h2>증명!</h2>
    </template>
  </Child>
</template>

<script>
import Child from "./components/Child.vue";
export default {
  components: {
    Child,
  },
};
</script>

//자식 컴포넌트
<template>
  <slot name="test1">부모 컴포넌트에서 작성된 내용이 없을때 출력 하는 text1</slot>
  <slot name="test2">부모 컴포넌트에서 작성된 내용이 없을때 출력 하는 text2</slot>
</template>

<script>
export default {};
</script>



emit: 자식 컴포넌트에서 부모 컴포넌트에게 이벤트를 전달한다 
 
1 자식 컴포넌트의 script 영역에 emits라는 옵션을 만들고 [](배열)에 형태로 정의한다 emits는 emit들을 모아놓은 옵션이다
2 emit을 태그와 연결 할 때에는 $emit을 사용한다 이때 $는 의미를 가진다 라고 정의 할 수 있는데 특별한 기능은 없다 
즉 vue에서 $는 $다음에 어떠한 속성이 나오면 해당 속성은 vue에서 사용하는 속성이라는 의미를 지닌다
3 자식 컴포넌트 에서 $emit은 ()안에 파라미터를 작성 할 수있는데 이때 () 안에 들어가는 1번파라미터 에는  emits에 정의한 이름이 들어가고 , 2번파라미터에는 자식 컴포넌트에 정의된 데이터를 보낼 수 있다
 부모 컴포넌트에서 emit으로 정의한 이벤트를 명시한다
4 위 내용은 emit으로 부모 컴포넌트에게 이벤트를 전달 하는 과정이고 아래 예시를 참조 해 주길 바람  
ex)

//부모 컴포넌트 

<template>
  <Mybtn @test="log"></Mybtn>
  <!-- 자식 컴포넌트에서 test라는 이벤트를 만들었고 해당 이벤트는 click 이벤트가 부여된 이벤트로 써 부모컴포넌트의 log라는 mothod를 실행시킴  -->
</template>

<script>
import Mybtn from "./components/MyBtn.vue";
export default {
  components: {
    Mybtn,
  },
  methods: {
    log() {
      console.log("버튼 클릭");
    },
  },
};
</script>

//자식 컴포넌트 
<template>
  <button class="btn" @click="$emit('test',<자식 컴포넌트의 데이터>)">MyBtn 컴포넌트</button>
  <!-- button이라는 요소의 v-on:click 즉 클릭이벤트를  emit에 적용 이때 $emit은 emit이라는 기능을 사용한다는 의미 ()안에 인자는 emit의 이름  -->
  <!-- 이제부터 test라는 이벤트는 click 이라는 기능이 부여됨  -->
  
</template>

<script>
export default {
  emits: ["test"],
}; 
// emits에서 test 라는 emit 만듬 
</script>

<style scoped>
.btn {
  display: inline-block;
  margin: 4px;
  padding: 6px 12px;
  border-radius: 4px;
  background-color: gray;
  color: white;
  cursor: pointer;
}
</style>

위코드에서 2번 파라미터에 자식 컴포넌트에서 전달할 데이터는 생략 할 수 있다.

2번 파라미터에서 자식이보낸 데이터는 부모 컴포넌트에서 $event에 저장되기 때문에 $event를 이용해서 자식컴포넌트가 보낸 데이터를 사용 한다 




provide inject:
1부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달 하기위해선 props를 사용한다
2그렇다면 부모컴포넌트에서 손자 컴포넌트(자식에 자식)에게 데이터를 전달하기위해선 props는 어떻게 동작해야 하는가?
3props의 기능은 부모컴포넌트가 자식 컴포넌트로 데이터를 전달하는 기능을 하므로 손자 컴포넌트 에게 데이터를 전달하기 위해선 자식 컴포넌트를 거쳐야한다 
4provide,inject는 손자 컴포넌트에게 데이터를 전달하기 위한 중간 과정인 부모 컴포넌트를 거쳐야하는 상황을 생략 할 수 있게 하는 기능을 가진다  
즉 상위 컴포넌트가 하위 컴포넌트에게 데이터를 중간 과정없이 다이렉트로 보내는 것이다

Provide = 
1제공하다라는 의미로 데이터를 제공해 준다
2 Provide와 inject는 props가 중간 과정을 거쳐야한다는 단점을 보완한 것이다
3 그렇다면 데이터를 제공하는 입장은 누구일까? 상위 컴포넌트이다 즉 provide는 상위 컴포넌트에 명시한다 
4 provide 는 함수 형태로 데이터를 제공한다
주의사항! : provide로 제공된 데이터는 반응형 데이터가 아니기 때문에 기본적으로 이벤트 핸들링을 할 수 없다 

computed를 이용해서 반응형 데이터로 만들어 줄 수 있으나 전역상태관리(vuex,pinia) 사용을 권장한다 
inject =
1 주입하다라는 의미로 데이터를 제공받는다
2 데이터를 제공받는 입장은 누구일까? 하위 컴포넌트이다 즉 inject는 하위 컴포넌트에 명시한다 
3 inject는 배열 형태로 데이터를 제공받는다

ex)

//조상 컴포넌트 
<template>
  <Parent></Parent>
</template>

<script>
import Parent from "./components/Parent.vue";
export default {
  data() {
    return {
      message: "root에서 보내는 메세지",
    };
  },
  components: {
    Parent,
  },
  provide() {
    return {
      msg: this.message,
    };
  },
};
</script>
//부모 컴포넌트
<template>
  <Child></Child>
</template>

<script>
import Child from "./Child.vue";
export default {
  components: {
    Child,
  },
};
</script>

//손자 컴포넌트
<template>
  <h1>{{ msg }}</h1>
</template>

<script>
export default {
  inject: ["msg"],
};
</script>



ref = reference의 약어로 참조 한다는 의미이다

1 vue에서 mounted가 실행되면 뷰 인스턴스가 화면에 그려지기 때문에 DOM API로 접근이 가능하다
2 ref는 주로 DOM API처럼 html요소에 접근 하는 용도로 사용한다
3 이때 ref속성은 해당 요소에 이름을 지어주는것과 같다 
4 mounted안에서 ref를 참조하기위해선 $refs을사용한다 refs는 해당 컴포넌트에서 작성된 모든 ref를 가지고 있다
5 부모 컴포넌트에서 자식 컴포넌트에서 작성된 요소를 참조 할 수 있다. 
ex)

// 부모 컴포넌트
<template>
  <Child ref="child"></Child> 
  // 자식 컴포넌트에 ref라는 속성부여
  <h1 ref="ref1">ref로 참조할 요소의 이름을 만들어 줍니다</h1>
  <h2 ref="ref2">mounted에서 해당 ref를 $refs를 사용 해 참조 해 보겠습니다</h2>
  <h2 ref="console">console창을 확인 해 보세요!</h2>
</template>

<script>
import Child from "./components/Child.vue";
export default {
  mounted() {
    console.log(this.$refs.ref1);
    console.log(this.$refs.ref2);
    console.log(this.$refs.console);
    console.log(this.$refs.child.$refs.h2El);
    //자식 컴포넌트의 ref가 h2El인 요소를 찾는 코드
  },
  components: { Child },
};
</script>

//자식 컴포넌트
<template>
  <h1>자식 컴포넌트에 작성된 h1요소 입니다!</h1>
  <h2 ref="h2El">자식 컴포넌트에 작성된 h1요소 입니다!</h2>
</template>

<script>
export default {};
</script>