[Vue]Props

chaewonΒ·2024λ…„ 7μ›” 19일
0
post-thumbnail

πŸ’»Props

λΈ”λ‘œκ·Έλ₯Ό κ΅¬μΆ•ν•˜λŠ” 경우 λΈ”λ‘œκ·Έ κ²Œμ‹œκΈ€μ„ λ‚˜νƒ€λ‚΄λŠ” μ»΄ν¬λ„ŒνŠΈκ°€ μžˆλ‹€κ³  κ°€μ •ν•΄λ³΄μž μ΄λ•Œ λͺ¨λ“  λΈ”λ‘œκ·Έ κ²Œμ‹œκΈ€μ˜ UIλ‚˜ λ ˆμ΄μ•„μ›ƒμ€ λ™μΌν•˜μ§€λ§Œ κ²Œμ‹œκΈ€μ˜ 제λͺ©, λ‚΄μš©κ³Ό 같은 λ°μ΄ν„°λŠ” 각각 λ‹€λ₯΄λ‹€. 그러면 μ»΄ν¬λ„ŒνŠΈμ— 각각 제λͺ©μ΄λ‚˜ λ‚΄μš©κ³Ό 같은 데이터λ₯Ό 전달해야 ν•˜λŠ”λ° μ΄λ•Œ propsλ₯Ό μ‚¬μš©ν•˜μ—¬ μ»΄ν¬λ„ŒνŠΈλ‘œ 데이터(속성)을 전달할 수 μžˆλ‹€.

Props λž€?

  • Propsλž€? μ»΄ν¬λ„ŒνŠΈμ— 등둝할 수 μžˆλŠ” μ‚¬μš©μž μ •μ˜ μ†μ„±μž…λ‹ˆλ‹€. λΈ”λ‘œκ·Έ κ²Œμ‹œκΈ€ μ»΄ν¬λ„ŒνŠΈμ— μ‚¬μš©μž μ •μ˜ 속성을 μ„ μ–Έν•˜λ©΄ 이 μ»΄ν¬λ„ŒνŠΈλ₯Ό μ‚¬μš©ν•˜λŠ” λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ—μ„œ 데이터(속성)을 전달 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

1. Props μ„ μ–Έ

  • Vue μ»΄ν¬λ„ŒνŠΈμ—λŠ” λͺ…μ‹œμ  Props 선언이 ν•„μš”ν•©λ‹ˆλ‹€. μ™œλƒν•˜λ©΄ μ»΄ν¬λ„ŒνŠΈμ— μ „λ‹¬λœ μ™ΈλΆ€ propsκ°€ fallthrough μ†μ„±μœΌλ‘œ μ²˜λ¦¬λ˜μ–΄μ•Ό 함을 μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€.

    πŸ”§ fallthrough 속성
    props λ˜λŠ” emits에 λͺ…μ‹œμ μœΌλ‘œ μ„ μ–Έλ˜μ§€ μ•Šμ€ 속성 λ˜λŠ” 이벀트

1-1. λ¬Έμžμ—΄ λ°°μ—΄ μ„ μ–Έ

  • μ»΄ν¬λ„ŒνŠΈμ— props μ˜΅μ…˜μ„ μ‚¬μš©ν•˜μ—¬ μ„ μ–Έν•  수 μžˆλ‹€.
<script>
export default{
	props: [title],
  	setup(props){
  		console.log(props.title)
  	}
}
</script>

1-2. 객체문법 μ„ μ–Έ

  • λ¬Έμžμ—΄ 배열을 μ‚¬μš©ν•˜μ—¬ propsλ₯Ό μ„ μ–Έν•˜λŠ” 것 외에도 객체 문법을 μ‚¬μš©ν•˜μ—¬ 속성 νƒ€μž…κ³Ό ν•¨κ»˜ μ„ μ–Έ ν•  수 μžˆλ‹€.
<script>
export default{
	props: {
  		//key: value
  		title: String,
  		likes: Number
  	},
  	setup(props){
  		console.log(props.title)
  		console.log(props.likes)
  	}
}
</script>

porps μ„ μ–Έμ‹œ keyλŠ” 속성λͺ…이고 valueλŠ” 속성 νƒ€μž…μ΄λ‹€. 더 μžμ„Ένžˆ μ„ μ–Έν•˜κ³  μ‹ΆμœΌλ©΄ value에 κ³ κΈ‰ μ˜΅μ…˜μΈ 객체λ₯Ό μ„ μ–Έν•  수 μžˆλ‹€. vue μŠ€νƒ€μΌ κ°€μ΄λ“œμ—μ„œλŠ” λ¬Έμžμ—΄λ‘œ κ°„λ‹¨νžˆ μ„ μ–Έν•˜λŠ” 것 보닀 객체 νƒ€μž…μœΌλ‘œ λ””ν…ŒμΌν•˜κ²Œ μ„ μ–Έν•˜λŠ” 것을 ꢌμž₯ν•˜κ³  μžˆλ‹€.

  • type: String, Number, Boolean, Array, Object, Date, Function, Symbol λͺ¨λ“  κΈ°λ³Έ μƒμ„±μž λ˜λŠ” λͺ¨λ“  μ‚¬μš©μž μ •μ˜ νƒ€μž…μ΄ 올 수 μžˆλ‹€.(예: Person, Animal)
    그리고 [Number, String] 배열을 μ΄μš©ν•˜μ—¬ μ—¬λŸ¬κ°œμ˜ νƒ€μž…μ„ μ„ μ–Έν•  수 μžˆλ‹€.
  • default: 속성값이 λΉ„μ–΄ μžˆκ±°λ‚˜ undefinedλ₯Ό 전달 λ°›λŠ” 경우 기본값을 μ„ μ–Έν•  수 μžˆλ‹€. 그리고 객체 λ˜λŠ” λ°°μ—΄ νƒ€μž…μΈ 경우 기본값을 νŒ©ν† λ¦¬ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ λ°˜ν™˜ν•΄μ•Ό ν•œλ‹€.
  • required: 속성이 ν•„μˆ˜κ°’μ΄λΌλ©΄ true둜 ν•΄μ„œ μ„€μ •ν•  수 μžˆλ‹€.
  • validator: μ†μ„±κ°’μ˜ μœ νš¨μ„± 검사가 ν•„μš”ν•  λ•Œ μ‚¬μš©ν•  수 μžˆλ‹€.

✨ μ»΄ν¬λ„ŒνŠΈ μ‚¬μš© μ‹œ type, required, validator λͺ…μ‹œλœ 사항을 μœ„λ°˜ν•  λ•Œ 개발λͺ¨λ“œμ—μ„œ μ½˜μ†” κ²½κ³ κ°€ λ°œμƒν•œλ‹€.



`props`λ₯Ό μ΄μš©ν•œ μ˜ˆμ‹œλ₯Ό λ“€μ–΄λ³΄μž

AppCard.vue


//AppCard.vue

<template>
	<div class="card">
		<div class="card-body">
          	<!-- ν•­λͺ©μ— 맞게 λ„£μ–΄μ€€λ‹€. -->
			<h5 class="card-title red">{{ title }}</h5>
			<p class="card-text">{{ contents }}</p>
			<a href="#" class="btn btn-primary">Go somewhere</a>
		</div>
	</div>
</template>
  
<script>
export default {
  	//propsλΌλŠ” 속성을 μ„ μ–Έν•œλ‹€.
	props: ["title", "contents"],
	setup() {
		return {};
	},
};
</script>
<style></style>

TheView.vue

<script>

//TheView.vue
  
<template>
	<main>
		<div class="container text-center py-4">
			<div class="row g-3">
				<div class="col col-4">
                  	//AppCard.vue νŒŒμΌμ—μ„œ props μ„ μ–Έν•œ 것을 가져와 정적인 값을 쀄 수 μžˆλ‹€.
					<AppCard title="제λͺ©1" contents="λ‚΄μš©1"></AppCard>
				</div>
				<div class="col col-4">
                  	//λ°˜μ‘ν˜• 데이터λ₯Ό μ„ μ–Έν•˜μ—¬μ„œλ„ 넣을 수 μžˆλ‹€.(λ°”μΈλ”©ν•˜μ—¬ μ‚¬μš©)
					<AppCard :title="post.title" :contents="post.contents"></AppCard>
				</div>
				<div class="col col-4">
					<AppCard></AppCard>
				</div>
				<div class="col col-4">
					<AppCard></AppCard>
				</div>
				<div class="col col-4">
					<AppCard></AppCard>
				</div>
				<div class="col col-4">
					<AppCard></AppCard>
				</div>
				<div class="col col-4">
					<AppCard></AppCard>
				</div>
			</div>
		</div>
	</main>
</template>

<script>
import AppCard from "@/components/AppCard.vue";
import { reactive } from "vue";
export default {
	components: {
		AppCard,
	},
	setup() {
  		//λ°”μΈλ”©ν•˜μ—¬ μ‚¬μš©ν•  수 μžˆλ‹€.
		const post = reactive({
			title: "제λͺ©2",
			contents: "λ‚΄μš©2",
		});
		return { post };
	},
};
</script>

<style></style>

v-for을 μ΄μš©ν•΄μ„œ 루프λ₯Ό 돌릴 수 μžˆλ‹€.

TheView.vue

<template>
	<main>
		<div class="container text-center py-4">
			<div class="row g-3">
				<div v-for="post in posts" :key="post.id" class="col col-4">
					<AppCard :title="post.title" :contents="post.contents"></AppCard>
				</div>
			</div>
		</div>
	</main>
</template>

<script>
import AppCard from "@/components/AppCard.vue";
import { reactive } from "vue";
export default {
	components: {
		AppCard,
	},
	setup() {
		//v-for을 μ΄μš©ν•œ 루프
		const posts = reactive([
			{ id: 1, title: "제λͺ©1", contents: "λ‚΄μš©1" },
			{ id: 2, title: "제λͺ©2", contents: "λ‚΄μš©2" },
			{ id: 3, title: "제λͺ©3", contents: "λ‚΄μš©3" },
			{ id: 4, title: "제λͺ©4", contents: "λ‚΄μš©4" },
			{ id: 5, title: "제λͺ©5", contents: "λ‚΄μš©5" },
		]);

		return { posts };
	},
};
</script>

<style lang="scss" scoped></style>

v-for을 μ΄μš©ν•œ κ²°κ³Όν™”λ©΄


객체문법을 μ΄μš©ν•œ 방법
AppCard.vue

<template>
	<div class="card">
		<div class="card-body">
			<!-- type : new, notice -->
			<!-- <span class="badge text-bg-secondary">{{
				type == "news" ? "λ‰΄μŠ€" : "곡지사항"
			}}</span> -->
			<span class="badge text-bg-secondary"> {{ typeName }}</span>
			<h5 class="card-title red mt-2">{{ title }}</h5>
			<p class="card-text">{{ contents }}</p>

			<!-- v-ifλ₯Ό ν†΅ν•΄μ„œ isLikeκ°€ true일 경우 μœ„μ— μ•„λ‹κ²½μš° 밑에 νƒœκ·Έκ°€ λ…ΈμΆœλœλ‹€.-->
			<!-- <a href="#" v-if="isLike" class="btn btn-danger">μ’‹μ•„μš”</a>
			<a href="#" v-else class="btn btn-outline-danger">μ’‹μ•„μš”</a> -->

			<!-- computedλ₯Ό μ΄μš©ν•œ νƒœκ·Έ λ¬ΆκΈ° -->
			<a href="#" class="btn" :class="isLikeClass">μ’‹μ•„μš”</a>
		</div>
	</div>
</template>

<script>
import { computed } from "vue";

export default {
	//객체 νƒ€μž…μœΌλ‘œ μ„ μ–Έ
	props: {
		//속성을 μ •μ˜
		type: {
			type: String,
			default: "news",
			//νƒ€μž…μ΄ λͺ…ν™•νžˆ λ“€μ–΄κ°€ μžˆλŠ”μ§€ μœ νš¨μ„± 검사λ₯Ό μ§„ν–‰ν•œλ‹€. λ§Œμ•½ νƒ€μž…μ΄ 잘λͺ» λ“€μ–΄κ°€ 있으면 μ½˜μ†”μ— 'Invalid prop'λΌλŠ” 였λ₯˜λ₯Ό λ³Ό 수 μžˆλ‹€.
			validator: value => {
				return ["news", "notice"].includes(value);
			},
		},
		title: {
			type: String,
			required: true,
		},
		contents: {
			type: String,
			required: true,
		},
		isLike: {
			type: Boolean,
			default: false,
		},
		//λ ˆνΌλŸ°μŠ€νƒ€μž…(객체, λ°°μ—΄ λ“±) λ””ν΄νŠΈλ₯Ό μ„€μ •ν•  λ•ŒλŠ” 기본값을 λ°˜ν™˜ν•˜λŠ” νŒ©ν† λ¦¬ ν•¨μˆ˜λ₯Ό μ„ μ–Έν•΄μ•Ό ν•œλ‹€.
		obj: {
			type: Object,
			default: () => {
				return;
			},
		},
	},
	// setup() ν•¨μˆ˜μ˜ 첫 번째 λ§€κ°œλ³€μˆ˜λ‘œ porps 객체λ₯Ό λ°›μ•„ μ‚¬μš©ν•  수 μžˆλ‹€.
	setup(props) {
		// computedλ₯Ό μ΄μš©ν•΄ μ’‹μ•„μš”λ₯Ό ν•˜λ‚˜λ‘œ λ¬Άμ–΄λ³΄μž
		const isLikeClass = computed(() =>
			props.isLike ? "btn-danger" : "btn-outline-danger",
		);

		const typeName = computed(() =>
			props.type === "news" ? "λ‰΄μŠ€" : "곡지사항",
		);
		return { isLikeClass, typeName };
	},
};
</script>
<style></style>

2. 단방ν–₯ 데이터 흐름

λͺ¨λ“  propsλŠ” μƒμœ„ 속성과 ν•˜μœ„ 속성간에 단방ν–₯ λ°”μΈλ”©μœΌλ‘œ ν˜•μ„±λ˜μ–΄ μžˆλ‹€. λ§Œμ•½ μƒμœ„ 속성이 μ—…λ°μ΄νŠΈλ˜λ©΄ ν•˜μœ„ 속성도 μ—…λ°μ΄νŠΈλ˜μ§€λ§Œ κ·Έ λ°˜λŒ€λŠ” μ•„λ‹ˆλ‹€. μ΄λŸ¬ν•œ μ„±μ§ˆμ€ ν•˜μœ„ 속성 λ³€κ²½ μ‹€μˆ˜λ‘œ μƒμœ„ 속성을 λ³€κ²½ν•˜μ—¬ μ•±μ˜ 데이터 흐름을 μ΄ν•΄ν•˜κΈ° μ–΄λ ΅κ²Œ λ§Œλ“œλŠ” 것을 방지할 수 μžˆλ‹€.

λ˜ν•œ μƒμœ„ μ»΄ν¬λ„ŒνŠΈκ°€ μ—…λ°μ΄νŠΈλ  λ•Œλ§ˆλ‹€ ν•˜μœ„ μ»΄ν¬λ„ŒνŠΈμ˜ λͺ¨λ“  propsλŠ” μ΅œμ‹  μƒνƒœλ„ μ΅œκΈ°ν™” λœλ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— μžμ‹ μ»΄ν¬λ„ŒνŠΈ λ‚΄λΆ€μ—μ„œ propsλ₯Ό λ³€κ²½ν•˜μ§€ μ•Šμ•„μ•Ό ν•œλ‹€.


3. Boolean Casting

Booleanνƒ€μž…μ˜ PropsλŠ” νŠΉλ³„ν•œ μΊμŠ€νŒ… κ·œμΉ™μ΄ μžˆμŠ΅λ‹ˆλ‹€. <MyComponet>κ°€ λ‹€μŒκ³Ό 같이 μ„ μ–Έλ˜μ–΄ μžˆλ‹€.

<script>
	export default{
  		props: {
  			disabled: Boolean
  		}
  	}
</script>

MyComponentλŠ” λ‹€μŒκ³Ό 같이 μ‚¬μš©ν•  수 μžˆλ‹€.

<!-- :disabled="true" μ „λ‹¬ν•˜λŠ” 것과 λ™μΌν•˜λ‹€. -->
<MyComonent disabled>
<!-- :disabled="false" μ „λ‹¬ν•˜λŠ” 것과 λ™μΌν•˜λ‹€. -->
<MyComonent>
profile
μ˜λ¬Έμ€ 'μ‚Άμ˜ μˆ˜μ€€'을 κ²°μ •ν•˜κ³ , μ§ˆλ¬Έμ€ 'μ‚Ά 자체'λ₯Ό λ°”κΎΌλ‹€.

0개의 λŒ“κΈ€