21.02.22 lamplight서비스 프로젝트(FormRow 전역 컴포넌트 적용, 상황별 버튼 셋팅, 폰트 적용 등)

2021. 2. 22. 17:55Vue.js/Spring & Vue APP 프로젝트(프론트엔드)

# NOTE

@apply?
- tailwind 방식을 style에 적용할 수 있도록 해주는 것? 
- 즉, class에 css를 입력하는 tailwind를 style에 바로 입력하는 것 
https://tailwindcss.com/docs/functions-and-directives

# 소스코드

<FormRow.vue>

<template>
  <div class="form-row flex">
    <div class="w-32 flex justify-center ">
      <span class="flex items-center">{{title}}</span>
    </div>
    <div class="flex-grow justify-center">
      <slot></slot>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({  // 컴포넌트의 속성을 정의해주어야 함

  // title props의 속성을 정해준다
  props: {
    title: {
      type: String,
      required: true
    }
  },
  //컴포넌트의 이름을 정의한다
  name: 'FormRow'
})
</script>


<!--FormRow의 css를 post 방식으로 전송-->
<style lang="postcss">
.form-row-input{
  /* @apply? tailwind 방식을 style에 적용할 수 있도록 해주는 것? 
    즉, class에 css를 입력하는 tailwind를 style에 바로 입력하는 것  */
  /* rounded-sm =>	border-radius:0.125rem; */
  @apply w-full rounded-xl;

}

/* textarea에 달린 form-row-input 클래스 라는 의미*/
textarea.form-row-input{
  min-height: theme('spacing.96');
}

.form-row{
  /* mt => margin-top */
  @apply mt-2;
}

/*form-row 다음에 나오는 form-row라는 의미*/
.form-row + .form-row {

}

</style>


<style scoped>
  
</style> 

<App.vue>

<!-- vue를 하나의 jsp라고 생각하면 됨 -->

<template>


  <header class="header-bar h-40 bg-gray-100">
    <div class="container mx-auto flex h-full">
      <!-- router-link는 a와 같다고 보면 됨 -->
      <!-- to는 href -->
      <router-link to="/" class="h-full flex items-center">
        <img class="block w-20" src="./assets/logo.png" alt="">
      </router-link>

      <div class="flex-grow"></div>

      <nav class="header-bar__menu-box-1">
        <ul class="flex h-full">
          <li>
            <router-link to="/" class="h-full flex items-center font-bold px-10 hover:bg-black hover:text-white">
              HOME
            </router-link>
          </li>
          <li>
            <router-link to="/article/list" class="h-full flex items-center font-bold px-10 hover:bg-black hover:text-white">
              ARTICLE LIST
            </router-link>
          </li>
        </ul>
      </nav>
    </div>
  </header>

    
   <main>
    <!-- 이것을 해주어야 다른 페이지를 불러올 수 있음 -->
    <router-view></router-view>
  </main>

</template>

<script lang="ts">
import { defineComponent } from 'vue'


export default defineComponent({
  name: 'App'

})
</script>

<style lang="postcss">
.btn-primary {
  @apply py-2 px-4 bg-blue-600 hover:bg-blue-700 focus:ring-blue-500 focus:ring-offset-blue-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg;
}
.btn-secondary {
  @apply py-2 px-4 bg-gray-600 hover:bg-gray-700 focus:ring-gray-500 focus:ring-offset-gray-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg;
}
.btn-success {
  @apply py-2 px-4 bg-purple-600 hover:bg-purple-700 focus:ring-purple-500 focus:ring-offset-purple-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg;
}
.btn-danger {
  @apply py-2 px-4 bg-red-600 hover:bg-red-700 focus:ring-red-500 focus:ring-offset-red-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg;
}
.btn-warning {
  @apply py-2 px-4 bg-yellow-600 hover:bg-yellow-700 focus:ring-yellow-500 focus:ring-offset-yellow-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg;
}
.btn-info {
  @apply py-2 px-4 bg-green-600 hover:bg-green-700 focus:ring-green-500 focus:ring-offset-green-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg;
}

/* css 선택자 */
/* .btns 자식들 중에 class로 'btn-'를 갖고 있는 엘리먼트의 다음 엘리먼트 */
.btns > [class*="btn-"] + [class*="btn-"] {
  margin-left: theme('spacing.2');
}
</style> 

<index.css>

@tailwind base;
@tailwind components;
@tailwind utilities;




/* 여기에 css를 저장할 수 있음 */

@font-face {
  font-family: 'LotteMartDream';
  font-style: normal;
  font-weight: 400;
  src: url('https://cdn.jsdelivr.net/korean-webfonts/1/corps/lottemart/LotteMartDream/LotteMartDreamMedium.woff2') format('woff2'), url('https://cdn.jsdelivr.net/korean-webfonts/1/corps/lottemart/LotteMartDream/LotteMartDreamMedium.woff') format('woff');
}

@font-face {
  font-family: 'LotteMartDream';
  font-style: normal;
  font-weight: 700;
  src: url('https://cdn.jsdelivr.net/korean-webfonts/1/corps/lottemart/LotteMartDream/LotteMartDreamBold.woff2') format('woff2'), url('//cdn.jsdelivr.net/korean-webfonts/1/corps/lottemart/LotteMartDream/LotteMartDreamBold.woff') format('woff');
}

@font-face {
  font-family: 'LotteMartDream';
  font-style: normal;
  font-weight: 300;
  src: url('https://cdn.jsdelivr.net/korean-webfonts/1/corps/lottemart/LotteMartDream/LotteMartDreamLight.woff2') format('woff2'), url('https://cdn.jsdelivr.net/korean-webfonts/1/corps/lottemart/LotteMartDream/LotteMartDreamLight.woff') format('woff');
}

html, body {
  margin:0;
}

html {
  font-family: 'LotteMartDream', sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

<ArticleListPage.vue>

<template>

  <TitleBar class="bg-purple-500">Article List</TitleBar>

  <section class="article-write-form-box">
    <div class="container mx-auto">
      <form action="">
        <FormRow title="제목">
          <input type="text" class="form-row-input" placeholder="제목을 입력하세요."> 
        </FormRow>
        <FormRow title="내용">
          <textarea class="form-row-input" placeholder="내용을 입력하세요."></textarea>
        </FormRow>
        <FormRow>
          <!-- App.vue로 부터 .btn-primary의 style 가져오기 -->
          <div class="btns">
            <input class="btn-primary" type="button" value="등록">
            <input class="btn-success" type="button" value="등록">
            <input class="btn-info" type="button" value="등록">
            <input class="btn-warning" type="button" value="등록">
            <input class="btn-secondary" type="button" value="등록">
            <input class="btn-danger" type="button" value="등록">
          </div>
          
        </FormRow>
      </form>
    </div>
  </section>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
 /* 전역 컴포넌트 적용으로 안해도 됨 
import TitleBar from '../components/TitleBar.vue';
*/

export default defineComponent({
  name: 'ArticleListPage',
  
 /* 전역 컴포넌트 적용으로 안해도 됨 
  components: {
    TitleBar
  }
*/
})
</script>

<style scoped>

</style>