티스토리 뷰

cart html를 상위 컴포넌트로 이동시킨 후 하위 컴포넌트(product)에서 add to cart 버튼이 클릭됐을 때 장바구니 상태를 업데이트하도록 변경한다.
<!DOCTYPE html>
<html>
<head>
<title>App</title>
<link rel="stylesheet" type="text/css" href="./style.css">
</head>
<body>
<div class="nav-bar"></div>
<div id="app">
<div class="cart">
<p>Cart({{ cart.length }})</p>
</div>
<product :premium="premium" @add-to-cart="addToCart"></product>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="main.js"></script>
</body>
</html>
emit를 사용하면 광범위하게 이벤트가 전파 되기때문에 선호하지 않는 방법을 사용하고 있다. 🤔
Vue.component("product", {
props: {
premium: {
type: Boolean,
required: true
}
},
template: `
<div class="product">
<div class="product-image">
<img v-bind:src="image"/>
</div>
<div class="product-info">
<h1>{{ title }}</h1><span v-show="onSale">On Sale!</span>
<p v-if="inStock">In Stock</p>
<p v-else>Out of Stock</p>
<p>Shipping: {{ shipping }}</p>
<ul>
<li v-for="detail in details">{{ detail }}</li>
</ul>
<div class="color-box"
v-for="(variant, index) in variants"
:key="variant.variantId"
:style="{backgroundColor: variant.variantColor}"
@mouseover="updateProduct(index)"
>
</div>
<button v-on:click="addToCart"
:disabled="!inStock"
:class="{ disabledButton: !inStock }"
>Add to cart</button>
</div>
</div>
`,
data(){
return {
brand: 'Vue Mastery',
product: 'Socks',
selectedVarint: 0,
onSale: false,
details: ["80% cotton", "20% polyester", "Gender-neutral" ],
variants: [
{
variantId: 2234,
variantColor: "green",
variantImage: "./assets/vmSocks-green-onWhite.jpg",
variantQuantity: 10
},
{
variantId: 2235,
variantColor: "blue",
variantImage: "./assets/vmSocks-blue-onWhite.jpg",
variantQuantity: 0
}
],
cart: 0,
}
},
methods: {
addToCart(){
this.$emit("add-to-cart", this.variants[this.selectedVarint].variantId)
},
updateProduct(index){
this.selectedVarint = index
}
},
computed: {
title(){
return `${this.brand} ${this.product}`
},
image(){
return this.variants[this.selectedVarint].variantImage
},
inStock(){
return this.variants[this.selectedVarint].variantQuantity
},
shipping(){
if(this.premium){
return "Free"
} else {
return 2.99
}
}
}
})
var app = new Vue({
el: '#app',
data: {
premium: false,
cart: []
},
methods: {
addToCart(id){
this.cart.push(id)
}
}
})
리액트의 경우 상위 컴포넌트에서 작성한 함수를 자식 컴포넌트의 props로 넘겨줄 수 있다. 이벤트 전달 방식이 리액트와 무척 다른 점이다. 더 나은 방법이 있길...
댓글