프론트엔드

스벨트로 리스트&상세화면 구현하기

개발자R 2022. 6. 20. 13:33
반응형

스벨트 프로젝트 시작

npm install -g degit
npx degit sveltejs/template 프로젝트이름
cd 프로젝트이름
npm install
npm run dev

 

라우터 사용

npm install --save svelte-spa-router

 

App.svelte

<script>
  import List from "./List.svelte";
  import Detail from "./Detail.svelte";
  import Router from 'svelte-spa-router'

  const routes = {
    "/": List,
    "/detail/:id": Detail,
  };
</script>

<main>
  <Router {routes} />
</main>

<style>
  main {
    text-align: center;
    padding: 1em;
    max-width: 240px;
    margin: 0 auto;
  }

  h1 {
    color: #ff3e00;
    text-transform: uppercase;
    font-size: 4em;
    font-weight: 100;
  }

  @media (min-width: 640px) {
    main {
      max-width: none;
    }
  }
</style>

 

list.svelte

<script>
  import { onMount } from "svelte";
  import { push } from "svelte-spa-router";
  let today = new Date();

  let year = today.getFullYear();
  let month = ("0" + (today.getMonth() + 1)).slice(-2);
  let day = ("0" + today.getDate()).slice(-2);
  let hours = ("0" + today.getHours()).slice(-2);

  let dateString = year + "년 " + month + "월" + day + "일" + hours + ":00";

  let chartList = [];

  $: currentType = "domestic";

  const setChartType = (type) => {
    currentType = type;
    getChartList();
    console.log(currentType);
  };

  const getChartList = () => {
    fetch(`http://localhost:3300/~~~~~~~`)
      .then((response) => response.json())
      .then((data) => (chartList = data.chartList))
      .catch((error) => {
        console.log(error);
        return [];
      });
  };

  onMount(() => {
    getChartList();
  });

  const goDetail = (id) => {
    push(`/detail/${id}`);
  };
</script>

<h1>음악 차트</h1>
<p>{dateString}</p>
<div>
  <span
    on:click={() => setChartType("domestic")}
    class={currentType === "domestic" ? "selectedType" : ""}>국내</span
  >
  <span
    on:click={() => setChartType("overseas")}
    class={currentType === "overseas" ? "selectedType" : ""}>해외</span
  >
</div>

<div class="list-container">
  {#each chartList as chartData, idx}
    <div class="list-item-container">
      <p>{chartData.id}</p>
      <img src="imgs/{chartData.imageUrl}" alt="background image" />
      <p on:click={() => goDetail(chartData.id)} class="title list-item">
        {chartData.title}
      </p>
      <p class="list-item singer">{chartData.singer}</p>
    </div>
  {/each}
</div>

<style>
  .selectedType {
    color: red;
    font-weight: bolder;
  }

  .list-container {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    margin: 5rem 20rem;
  }

  .list-item-container {
    display: flex;
    align-items: center;
  }

  .list-item {
    padding: 1rem;
  }

  span {
    padding: 0.3rem;
  }

  .title {
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
    max-width: 15rem;
  }

  .singer {
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
    text-align: right;
    margin-left: auto;
  }
</style>

 

 

detail.svelte

<script>
  import { onMount } from "svelte/internal";
  import { pop } from "svelte-spa-router";
  export let params = {};
  let id;

  let chartData = {};

  const getChartDetail = () => {
    fetch(`http://localhost:3300/~~~~~`)
      .then((response) => response.json())
      .then((data) => {
        chartData = data.chart;
      })
      .catch((error) => {
        console.log(error);
        return [];
      });
  };

  onMount(() => {
    id = params.id;
    getChartDetail();
  });

  const goBack = () => {
    pop();
  };
</script>

<img class="arrow" on:click={goBack} src="imgs/back_arrow.png" alt="" />
<div style="height:5rem" />
<h1>{chartData.title}</h1>
<span>{chartData.singer}</span>
<div style="height:5rem" />
<div class="data">
  <div class="line">
    <div class="data-header">작사</div>
    <div class="data-value">{chartData.lyricist}</div>
  </div>
  <div class="line">
    <div class="data-header">작곡</div>
    <div class="data-value">{chartData.melodizer}</div>
  </div>
  <div class="line">
    <div class="data-header">장르</div>
    <div class="data-value">{chartData.genre}</div>
  </div>
</div>

<style>
  .arrow {
    position: fixed;
    left: 0;
    padding: 2rem;
  }

  .line {
    padding: 1rem;
    min-width: 15rem;
    max-width: 30rem;
    display: flex;
  }

  .data {
    display: inline-block;
  }

  .data-header {
    min-width: 5rem;
    text-align: right;
    margin-right: 3rem;
    font-weight: bold;
  }

  .data-value {
    text-align: left;
  }
</style>
반응형