Angular vs Svelte - 카드 구성요소

이전 게시물 중 일부를 확인하면 최근에 Svelte 및 Sapper로 몇 가지 실험을 하고 있음을 알 수 있습니다.

몇 년 동안 Angular로 작업했고 지금은 Svelte를 배우고 있기 때문에 일부 구성 요소를 Angular에서 Svelte로 마이그레이션하는 것이 유용할 수 있다고 생각했습니다.

이 기사에서는 차이점을 볼 수 있도록 Angular와 Svelte로 빌드된 다음 카드 구성 요소를 공유합니다.



I'm using tailwindcss as my utility-first CSS framework. If you're not familiar with tailwind, please checkout the official tailwindcss site. Also, if you want to start using tailwindcss with angular or with Svelte, I wrote the following articles:



모난



이 카드 구성 요소의 Angular 버전의 경우 다음과 같은 엽서 구성 요소를 만들어야 합니다.

// post-card.component.ts

import { Component, Input } from '@angular/core'

@Component({
    selector: 'post-card',
    templateUrl: './post-card.component.html',
    styleUrls: ['./post-card.component.css']
})

export class PostCardComponent {

    @Input() title;
    @Input() description;
    @Input() location;
    @Input() picUrl = 'https://i1.wp.com/www.foot.com/wp-content/uploads/2017/03/placeholder.gif?ssl=1'
    @Input() createdAt;
    @Input() labels = [];

    constructor() { }

    showMore() {
        alert("showing more...")
    }
}


  • @Input() 데코레이터를 사용하면 구성 요소 간에 데이터를 공유할 수 있습니다. @Input() 속성은 쓰기 가능하고 @Output() 속성은 관찰 가능합니다.

  • <!-- post-card.component.html -->
    
    <div class="flex flex-wrap shadow-lg rounded-lg overflow-hidden mb-6">
        <!-- Image -->
        <div class="w-full h-48 md:h-auto md:w-1/4 bg-cover bg-center" [style.backgroundImage]="'url('+ picUrl +')'"></div>
        <!-- Details -->
        <div class="w-full md:w-3/4 px-6 py-4 bg-white">
            <div class="py-2">
                <p class="text-2xl">{{title}}</p>
                <p class="text-sm text-gray-600 mb-2">{{createdAt | date:'MM/dd/yyyy'}}</p>
                <!-- Labels -->
                <div class="flex flex-wrap">
                    <p *ngFor="let label of labels"
                        class="border border-solid border-orange-500 rounded w-auto inline-block px-2 py-1 mr-3 text-sm mb-2">
                        {{label}}
                    </p>
                </div>
            </div>
            <p class="flex items-center text-sm mb-4">
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
                    <path class="heroicon-ui"
                        d="M4.06 13a8 8 0 0 0 5.18 6.51A18.5 18.5 0 0 1 8.02 13H4.06zm0-2h3.96a18.5 18.5 0 0 1 1.22-6.51A8 8 0 0 0 4.06 11zm15.88 0a8 8 0 0 0-5.18-6.51A18.5 18.5 0 0 1 15.98 11h3.96zm0 2h-3.96a18.5 18.5 0 0 1-1.22 6.51A8 8 0 0 0 19.94 13zm-9.92 0c.16 3.95 1.23 7 1.98 7s1.82-3.05 1.98-7h-3.96zm0-2h3.96c-.16-3.95-1.23-7-1.98-7s-1.82 3.05-1.98 7zM12 22a10 10 0 1 1 0-20 10 10 0 0 1 0 20z" />
                    </svg>
                <span class="ml-2">{{location}}</span>
            </p>
            <p class="mb-4">{{description}}</p>
            <div class="flex flex-wrap md:flex-row-reverse">
                <button (click)="showMore()"
                    class="w-full md:ml-2 px-4 py-3 rounded bg-orange-600 hover:bg-orange-500 mb-2 md:w-auto md:mb-0 text-white">
                    Show more
                </button>
            </div>
        </div>
    </div>
    


  • 파이프를 사용하여 날짜 형식을 변경하고 있습니다. 파이프는 데이터를 입력으로 받아 원하는 출력으로 변환합니다. 이 경우 자바스크립트 날짜를 'MM/dd/yyyy'로 변환합니다.
  • 다음과 같이 이중 중괄호를 사용하여 데이터 바인딩을 수행합니다. {{yourProperty}}
  • 카드 내에서 이미지를 배경 이미지로 설정하기 위해 다음과 같이 속성 바인딩을 사용하고 있습니다. [style.backgroundImage]="'url('+ picUrl +')'"
  • NgFor는 컬렉션의 각 항목에 대한 템플릿을 렌더링하는 구조적 지시어입니다. 이 경우 다음과 같이 각 레이블을 반복하는 데 사용하고 있습니다.

  • <p *ngFor="let label of labels" class="border border-solid border-orange-500 rounded w-auto inline-block px-2 py-1 mr-3 text-sm mb-2">
      {{label}}
    </p>
    


    용법



    엽서 구성 요소를 표시하기 위해 다음과 같이 AppComponent에 카드 속성을 추가합니다.

    // app.component.ts
    
    import { Component } from '@angular/core'
    
    @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css']
    })
    
    export class AppComponent {
      // This data will be sent to our post-card component
      card = {
        title: "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
        description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum",
        location: "New York",
        picUrl: "https://images.pexels.com/photos/1060803/pexels-photo-1060803.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
        createdAt: new Date(),
        labels: ["Travel", "People"]
      }
    
      constructor() { }
      }
    }
    
    



    <!-- app.component.html -->
    <post-card  [title]="card.title" 
                [description]="card.description"
                [location]="card.location"
                [picUrl]="card.picUrl"
                [createdAt]="card.createdAt"
                [labels]="card.labels">
    </post-card>
    


  • 이번에는 속성 바인딩을 사용하여 AppComponent에서 PostCardComponent로 데이터를 보냅니다.

  • 날씬한



    이제 Svelte를 사용하여 정확히 동일한 구성 요소를 빌드해 보겠습니다.

    <!-- PostCard.svelte -->
    
    <script>
      export let title
      export let description
      export let location
      export let picUrl = 'https://i1.wp.com/www.foot.com/wp-content/uploads/2017/03/placeholder.gif?ssl=1'
      export let createdAt
      export let labels = []
    
      function showMore() {
        alert("Showing more...")
      }
    </script>
    
    <div class="flex flex-wrap shadow-lg rounded-lg overflow-hidden mb-6">
      <!-- Image -->
      <div class="w-full h-48 md:h-auto md:w-1/4 bg-cover bg-center" style="background-image: url('{picUrl}')"></div>
      <!-- Details -->
      <div class="w-full md:w-3/4 px-6 py-4 bg-white">
        <div class="py-2">
          <p class="text-2xl">{title}</p>
          <p class="text-sm text-gray-600 mb-2">{createdAt.toLocaleDateString()}</p>
          <!-- Labels -->
          <div class="flex flex-wrap">
            {#each labels as label}
              <p
                class="border border-solid border-orange-500 rounded w-auto inline-block px-2 py-1 mr-3 text-sm mb-2">
                {label}
              </p>
            {/each}
          </div>
        </div>
        <p class="flex items-center text-sm mb-4">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path class="heroicon-ui" d="M4.06 13a8 8 0 0 0 5.18 6.51A18.5 18.5 0 0 1 8.02 13H4.06zm0-2h3.96a18.5 18.5 0 0 1 1.22-6.51A8 8 0 0 0 4.06 11zm15.88 0a8 8 0 0 0-5.18-6.51A18.5 18.5 0 0 1 15.98 11h3.96zm0 2h-3.96a18.5 18.5 0 0 1-1.22 6.51A8 8 0 0 0 19.94 13zm-9.92 0c.16 3.95 1.23 7 1.98 7s1.82-3.05 1.98-7h-3.96zm0-2h3.96c-.16-3.95-1.23-7-1.98-7s-1.82 3.05-1.98 7zM12 22a10 10 0 1 1 0-20 10 10 0 0 1 0 20z"/></svg>
            <span class="ml-2">{location}</span>
        </p>
        <p class="mb-4">{description}</p>
        <div class="flex flex-wrap md:flex-row-reverse">
          <button
            on:click={showMore}
            class="w-full md:ml-2 px-4 py-3 rounded bg-orange-600 hover:bg-orange-500 mb-2 md:w-auto md:mb-0 text-white">
            Show more
          </button>
        </div>
      </div>
    </div>
    


  • 파이프를 사용하는 대신 {createdAt.toLocaleDateString()} 를 사용하여 javascript 날짜 형식을 지정합니다.
  • 다음과 같이 단일 중괄호를 사용하여 데이터 바인딩을 수행합니다. {yourProperty}
  • 카드 내에서 이미지를 배경 이미지로 설정하기 위해 다음과 같이 데이터 바인딩을 사용하고 있습니다. style="background-image: url('{picUrl}')"
  • Svelte는 항목을 반복하는 구조적 지시문을 사용하는 대신 각 블록을 사용합니다.

  • {#each labels as label}
      <p class="border border-solid border-orange-500 rounded w-auto inline-block px-2 py-1 mr-3 text-sm mb-2">
        {label}
      </p>
    {/each}
    


    용법




    <!-- OtherSvelteComponent.Svelte -->
    <script>
        import PostCard from "../components/PostCard.svelte";
        // This data will be sent to our post-card component
        const card = {
            title: "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
            description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum",
            location: "New York",
            picUrl: "https://images.pexels.com/photos/1060803/pexels-photo-1060803.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
            createdAt: new Date(),
            labels: ["Travel", "People"]
        }
    
    </script>
    
    <PostCard {...card} />
    


    마지막 생각들



    알다시피 Svelte 구현은 더 작습니다. 더 정확하게 말하면 2817(Angular)에 비해 2348자(Svelte)로 20% 작습니다.
    20%가 큰 차이가 아니라고 생각할 수 있지만 구성 요소가 작을수록 두 구현 간의 차이가 커집니다.
    그 점을 증명하기 위해 매우 기본적인 예를 살펴보겠습니다.

    // Angular - HelloWorld component
    import { Component } from '@angular/core';
    
    @Component({
      selector: 'hello-world',
      template: '<p>{{message}}</p>',
      styleUrls: ['./hello-world.component.css']
    })
    export class HelloWorldComponent {
    
      message = "Hello world"
    
      constructor() { }
    }
    



    <!-- Svelte - HelloWorld component -->
    
    <script>
      let message = "Hello world"
    </script>
    
    <p>{message}</p>
    


    이 경우 Svelte 구성 요소는 400% 작습니다. 59자에 비해 224자(Angular)입니다. 이것이 부가가치입니다! 구성 요소를 가능한 한 작고 원자 단위로 유지하면 훨씬 적은 코드를 작성할 수 있습니다.

    Svelte에 대해 어떻게 생각하세요? 아직 사용해 보셨나요?



    아래 댓글로 알려주세요!

    좋은 웹페이지 즐겨찾기