재사용 가능한 독립된 모듈로 주로 React를 한번쯤은 다뤄봤다면 아주 흔한 개념이다.
이는 Ember에서도 동일하게 있는데 한번 알아보자
라우터 내부나 다른 컴포넌트 또 그 컴포넌트 안에 컴포넌트 이렇게 React처럼 중첩이 가능하다.
우리가 index route에 있다고 가정했을 때 제품목록 안에 2개의 제품이 있다
그럼 각 제품 카드들의 프로덕트 모양은 동일할텐데 이미지 관련 로직이나 다른 구성들이 동일하게 동작한다면 이는 중복됨으로 하나의 컴포넌트로 처리하는 것이 맞다.
직접적인 전체 코드를 가져오진 않고 component
를 어떻게 만들고 어떻게 사용하는 지에대해서 간단하게 다루고 넘어가보자
컴포넌트를 처음 만들때도 동일하게 emberCLI를 사용해 만들 예정이다
ember g component general-container
이러면 app/components/general-container.hbs
라는 파일이 생성되게 된다.
이를 통해 general-container.hbs
라는 컴포넌트를 만들고 다른 곳에서도 동일하게 컴포넌트를 통해 동일한 로직과 기능을 재사용 할 수 있게 된다.
일단 저번 글에서 만들었던 장바구니로 가는 버튼을 컴포넌트로 만든다면
<!-- app/components/general-container.hbs-->
<LinkTo @route="cart" class="cart_link">
cart
</LinkTo>
<main class="container mt-5">
{{yield}}
</main>
이런식으로 추가 하게 됐는데 아까 index
에서 사용하던 페이지 모양하고 동일하며 코드 중간을 보면 {{yield}}
라는 특이한 게 있다.
이는 쉽게 말하면 React에서 사용하던 {children}
과 같은 것으로 외부에서 해당 위치의 구성요소를 직접적으로 컨트롤 할 수 있게 되는 것이다.
이를 통해 공통적인 부분은 두고 나머지 변할 수 있는 부분의 확장성을 고려한 컴포넌트를 작성할 수 있다.
그럼 이걸 어떻게 사용해야 하는가?
우리가 React를 사용할 때는 함수형 컴포넌트를 만들고 이를 export
시킨 후 import
하여 사용하였는데 ember는 따로 import하는 부분이 존재하진 않는다
<!-- app/templates/index.hbs -->
<GeneralContainer>
<LinkTo @route="item" @model="1">Product 1</LinkTo>
<LinkTo @route="item" @model="2">Product 2</LinkTo>
</GeneralContainer>
import
도 없이 그냥 코드 자체를 이렇게 작성할 경우 이전에 작성한 코드랑 동일하게 동작하는 것을 볼 수 있다.
작성된 코드를 보면 굉장히 특이한데 component의 파일 명은 general-container
인데 사용되는 부분은 <GeneralContainer>
로 사용되고 있다.
이를 통해 코드 베이스 내부에 대시 케이스가 있더라도 엠버 구성요소 이름이 어떻게 되어 있는지 알 수 있다.(첫글자는 대글자여야 하고 카멜케이스로 작성해야한다)
이를 통해 item
페이지도 변경하자면
<!-- app/tmeplates/item.hbs -->
<GeneralContainer>
ITEM :{{this.model}}
product
</GeneralContainer>
이도 index
처럼 동일하게 동작하는 걸 볼 수 있다
그럼 {{yeild}}
말고 React에서 자식 컴포넌트에게 필요한 데이터를 넘겨주던 props
방식은 어떻게 사용할까??
이는 Product 상세페이지로 이동하는 링크 컴포넌트도 하나 만들어서 테스트해보자
똑같이 emberCLI를 사용해 component를 하나 만든다
ember g component product
<!-- app/coomponents/product -->
<LinkTo @route="item" @model="1" class="product">
<div class="product-image">
<img src="/assets/images/headphone.png" alt="" />
</div>
<div class="product-details">
<h3>title</h3>
</div>
</LinkTo>
product
컴포넌트를 만들다 보니 image
가 들어가는 부분이 생기는데 이 부분도 컴포넌트를 하나 만들어보자. 이때의 컴포넌트는 product
의 컴포넌트로 사용하기 위해
ember g component product/image
이러면 파일 구조가 components/product/image.hbs
로 하나가 생기는데 이러면 똑같이 <Image/>
이런식으로 사요하면 될까?
조금 다르다
일단 product
에서 작성한 img
태그 부분을 잘라내서 Image 컴포넌트에 옮긴 뒤 실제로 사용할 때는
<!-- app/coomponents/product -->
<LinkTo @route="item" @model="1" class="product">
<Product::Image />
<div class="product-details">
<h3>title</h3>
</div>
</LinkTo>
이런 식으로 <Produt::Image/>
::
를 사용해서 접근할 수 있다
이걸 동일하게 detail 부분에도 사용한다면 emberCLI통해 component를 만들고 Product::Detail
을 통해 컴포넌트를 사용할 수 있다