import { useState } from 'react';
import Counter from './Counter.js'; // Vue와 차이점 중 하나로 컴포넌트릉 import할 때는 상위에 명시해주고 활용하면 끝!
const Parent = () => {
const [value, setValue] = useState(0);
return (
<div>
<Counter value={value} />
</div>
)
}
export default Parent;
props
라는 개념이 있다.props
는 기본적으로 단방향 데이터 전달방식이다.props
를 전달 할때는 자식 컴포넌트에게 props이름={전달할데이터}
로 명시해준다.<!-- 부모 컴포넌트 -->
<template>
<!-- props의 이름은 자유롭게 작명이 가능 -->
<Counter :value="value" />
<!-- 혹은 -->
<Counter v-bind:value="value" />
</temlplate>
<script>
import Counter from './Counter.vue';
export default {
name: "Parent",
components: { Counter }, // React와의 차이점에서 컴포넌트를 import하고 components라는 객체에 등록을 해야 활용 가능하다.
data() {
return{
value: 0,
}
}
}
</script>
v-bind
혹은 :
의 키워드를 활용해서 전달하고 자식컴포넌트에서는 props
객체를 통해 부모로 부터 받아오는 데이터를 등록하고 전달 받는다.React에서는 전달 받은 props
를 렌더링 하기 위해서는 { }
를 활용하여 렌더링 한다.
const Counter = (props) => {
return (
<div>{ props.value }</div>
)
}
// 혹은 구조 분해 할당으로도 표현할 수 있다.
const Counter = ({ value }) => {
return (
<div>{ value }</div>
)
}
export default Counter;
Vue에서는 전달 받은 props
를 렌더링 하기 위해서는 {{ }}
를 활용하여 렌더링 한다.
{{ }}
를 콧수염 구문(Mustache Syntax)이라고 칭한다.<!-- 자식컴포넌트 -->
<template>
<div>{{ value }}</div>
</template>
<script>
export default {
name: "Counter",
props: ['value'], // 배열로 등록할 때는 props의 이름만 적어주면 된다.
props: {
value: Number, // 객체로 등록할 때는 props의 이름과 타입을 명시해줘야 한다. => { props이름 : 타입 }
}
}
</script>
위의 내용들을 토대로 가장 기초적인 Counter 기능을 만들어 보자
import { useState } from 'react';
// 부모 컴포넌트
const Parent = () => {
// 넘겨줄 데이터 선언
const [value, setValue] = useState(0);
// value를 증가시킬 함수 생성
const increase = () => {
setValue(prev => prev + 1)
}
// value를 감소시킬 함수 생성
const decrease = () => {
setValue(prev => prev - 1)
}
return (
{/* value라는 데이터와 이 데이터를 증감 시킬 increase, decrease함수를 props로 전달 */}
<Counter value={value} onIncrease={increase} onDecrease={decrease} />
)
}
// 자식 컴포넌트
const Counter = ({ value, onIncrease, onDecrease }) => {
return (
{/* props로 받은 value를 렌더링 */}
<div>{ value }</div>
{/* 버튼에 onClick이벤트를 부여해 props로 받는 함수를 직접 실행 */}
<button onClick={onDecrease}>-1</button>
{/* 버튼에 onClick이벤트를 부여해 props로 받는 함수를 직접 실행 */}
<button onClick={onIncrease}>+1</button>
)
}
export default Counter;
<!-- 부모컴포넌트 -->
<template>
<div>
<Counter :value="value" @onIncrease="increase" @onDecrease="decrease" />
</div>
</template>
<script>
import Counter from './Counter.vue';
export default {
name: 'ParentVue',
components: { Counter },
data() {
return {
value: 0,
};
},
methods: {
increase() {
this.value + 1; // Vue에서는 data(state)에 접근할 때는 this를 활용한다. 그래서 화살표함수는 사용할 수 없다.
},
decrease() {
this.value - 1;
},
},
}
</script>
<!-- 자식컴포넌트 -->
<template>
<div>
<!-- 부모에게서 받은 props데이터를 렌더링 -->
<div>{{ value }}</div>
<!-- 감소 함수를 직접 실행시키는 것이 아닌 부모 컴포넌트의 decrease함수를 실행시키는 요청을 진행 -->
<button @click="onDecrease">-1</button>
<!-- 증가 함수를 직접 실행시키는 것이 아닌 부모 컴포넌트의 increase함수를 실행시키는 요청을 진행 -->
<button @click="onIncrease">+1</button>
</div>
</template>
<script>
export default {
name: 'CounterVue',
props: {
value: Number,
},
methods: {
onIncrease() {
this.$emit('onIncrease') // 이 $emit이 React와 Vue의 고유의 특징 차이라고 생각한다.
},
onDecrease() {
this.$emit('onDecrease')
},
},
};
</script>
props
로 내려주면 그 함수를 받아서 자식컴포넌트가 사용하는 형식으로 작동한다.props
로 받아서 사용하는 것이 아니고 자식컴포넌트에서 $emit
을 통해 실행시키고자 하는 함수를 명시해 이벤트 요청을 발생시키면 부모컴포넌트에서 그 요청을 받아 해당 함수를 실행시키는 느낌으로 이해했다.