반응형

07. 리스트와 아이콘 사용법

앱UI제작

  • 리스트와 아이콘의 사용법 학습
  • 실전과 비슷한 예제를 통해서 사용법 학습

data :{}는 단일 데이터

data(){}는 return은 필수이며 return으로 값을 호출 할 수 있다. 재사용 다시 렌더링하려면 함수형식으로 사용

  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <!-- |Material+icon 아이콘 같이 사용하려면 기입 -->
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900&display=swap|Material+icon"
      rel="stylesheet"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/@mdi/font@7.0.96/css/materialdesignicons.min.css"
      rel="stylesheet"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css"
      rel="stylesheet"
    />
    <link
      href="https://fonts.googleapis.com/css?family=Material+Icons"
      rel="stylesheet"
    />

    <title>vuetify practice</title>
    <style></style>
  </head>
  <body>
    <div id="app">
      <v-app>
        <v-app-bar color="orange" dark app>
          <!-- 좌측에 메뉴 아이콘 추가     -->
          <v-app-bar-nav-icon></v-app-bar-nav-icon>
          <v-toolbar-title>Virtual Company</v-toolbar-title>
        </v-app-bar>
        <v-main>
          <v-container>
            <v-card>
              <v-list two-line v-for="item in aList" :key="item.title">
                <!-- 항목을 하나씩 가져와서 item 단위로 표시 -->

                <v-list-item @click="">
                  <!-- 좌측에 대표 아이콘 먼저 표시 -->
                  <v-list-item-avatar>
                    <v-icon :class="item.icon_style">
                      {{item.icon_name}}
                    </v-icon>
                  </v-list-item-avatar>
                  <!-- 제목 렌더링 -->
                  <v-list-item-content>
                    <v-list-item-tilte>{{item.title}}</v-list-item-tilte>
                  </v-list-item-content>
                  <v-list-item-action>
                    <v-btn icon>
                      <v-icon class="material-symbols-outlined"
                        >keyboard_arrow_right</v-icon
                      >
                    </v-btn>
                  </v-list-item-action>
                </v-list-item>
              </v-list>
            </v-card>

            <v-btn fab dark color="red">
              <v-icon>add</v-icon>
            </v-btn>
          </v-container>
        </v-main>
        <v-footer></v-footer>
      </v-app>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.js"></script>
    <script>
      new Vue({
        el: "#app",
        vuetify: new Vuetify(),
        data() {
          // 반복되는 항목들은 JSON 배열 데이터로 만들어 반환
          return {
            aList: [
              {
                icon_style: "red white--text ",
                icon_name: "account_balance",
                title: "Create List",
              },
              {
                icon_style: "green white--text ",
                icon_name: "photo",
                title: "Use Material Icon",
              },
              {
                divider: false,
                icon_style: "yellow white--text",
                icon_name: "movie",
                title: "List & Icons",
              },
            ],
          };
        },
      });
    </script>
  </body>

 

08.하단 네비게이션

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <!-- |Material+icon 아이콘 같이 사용하려면 기입 -->
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900&display=swap"
      rel="stylesheet"
    />

    <link
      href="https://fonts.googleapis.com/css?family=Material+Icons"
      rel="stylesheet"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/@mdi/font@7.0.96/css/materialdesignicons.min.css"
      rel="stylesheet"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css"
      rel="stylesheet"
    />

    <title>vuetify practice</title>
    <style></style>
  </head>
  <body>
    <div id="app">
      <v-app>
        <v-main>
          <v-card
            height="100%"
            class="d-flex display-2 align-center justify-center"
          >
            선택:{{sSelect}}
          </v-card>
        </v-main>
        <v-footer>
          <!-- 선택된 메뉴는 sSelect 데이터를 연동시켜 바인딩 -->
          <v-bottom-navigation absolute v-model="sSelect" dark>
            <!-- 아이콘 버튼 3개 표시 -->
            <v-btn color="red" text value="자전거"
              >자전거
              <v-icon>directions_bike</v-icon>
            </v-btn>
            <v-btn color="red" text value="지하철"
              >지하철
              <v-icon>subway</v-icon>
            </v-btn>
            <v-btn color="red" text value="버스"
              >버스
              <v-icon>directions_bus</v-icon>
            </v-btn>
          </v-bottom-navigation>
        </v-footer>
      </v-app>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.js"></script>
    <script>
      new Vue({
        el: "#app",
        vuetify: new Vuetify(),
        data() {
          return {
            sSelect: "자전거",
          };
        },
      });
    </script>
  </body>

09. 탐색 서럽

탐색 서랍(Navigation drawer)UI

  • 앱바의 메뉴 아이콘을 누르면 탐색 서랍표시
  • 링크를 클릭하면 해당 사이트로 이동
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <!-- |Material+icon 아이콘 같이 사용하려면 기입 -->
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900&display=swap"
      rel="stylesheet"
    />

    <link
      href="https://fonts.googleapis.com/css?family=Material+Icons"
      rel="stylesheet"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/@mdi/font@7.0.96/css/materialdesignicons.min.css"
      rel="stylesheet"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css"
      rel="stylesheet"
    />
    <script
      src="https://kit.fontawesome.com/86e4e86e0d.js"
      crossorigin="anonymous"
    ></script>
    <title>vuetify practice</title>
    <style></style>
  </head>
  <body>
    <div id="app">
      <v-app>
        <v-app-bar app color="primary" dark>
          <!-- 메뉴 아이콘을 누르면 클릭기능 비활성화 -->
          <v-app-bar-nav-icon
            @click.stop="bDrawer = !bDrawer"
          ></v-app-bar-nav-icon>
          <v-toolbar-title>Header입니다</v-toolbar-title>
          <!-- bDrawerrk True 이면 탐색 서랍 사용하도록 바인딩 -->
        </v-app-bar>
        <v-navigation-drawer
          absolute
          temporary
          v-model="bDrawer"
        ></v-navigation-drawer>
      </v-app>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.js"></script>
    <script>
      new Vue({
        el: "#app",
        vuetify: new Vuetify(),
        data() {
          return {
            //버튼을 누르면 비활성화되도록 하는 토글 변수
            bDrawer: false,
            //배열로 메뉴의 제목, 아이콘, 링크 준비
            menu_items: [],
          };
        },
      });
    </script>
  </body>

라우터로 멀티페이지 관리하는 SPA 만들기

본격적인 실전 프로젝트 시작

  • 뷰티파이에서 제공하는 Vue-CLI 템플릿
  • 메인페이지와 서브페이지로 이동하는 라우터 기능 구현

 

public  정적파일만 담겨질수있음

src 개발한 파일들이 담겨져있는 폴더

dist build를 통한 결과 폴더

 

vue add vuetify

 

** 공부

seo

mpa - 페이지마다 한번씩 로딩 

spa - 처음로딩이 느림 그후에는 계속 

 

04. Vuex로 상태값 관리하는 SPA 만들기

Vuex로 상태값 관리

  • 뷰티파이로 디자인한 메인페이지에서 입력한 내용을 Vuex에 저장
  • 그 값을 서브페이지에서 전달받아 관리
728x90
반응형

03. 뷰티파이 기초 쌓기

간단하게 Vue에서 사용하는 UI프레임워크

- 01. 뷰티파이, 뷰 최고의 UI프레임워크

뷰티파이(Vuetify.js)란 무엇인가?

  • 뷰 자바스크립트 프레임워크에 머티리얼 디자인을 사용할 수 있는 컴포넌트 프레임워크
  • 구글의 머티리얼 디자인 스펙2를 충실하게 표현
  • 현대 웹앱에 필요한 컴포넌트를 편리하게 사용

뷰티파이가 주목받는 4가지 특징

  1. 구글 머티리얼 스펙의 충실한 지원
  2. 80개 이상의 시맨틱 머티리얼 디자인 컴포넌트
  3. 빠른 속도
  4. 쉬운 학습곡선

- 02. 기본 레이아웃 만들기 1

삼단 레이아웃 실습

  • 모바일 UI의 가장 기본이 되는 툴바, 본문, 바닥글의 삼단 레이아웃을 구성

핵심 내용

  • 틀바 영역: v-toolbar 엘리먼트 사용
  • 본분 영역: v-main 엘리먼트 사용
  • 여백 자동 설정: v-container 엘리먼트 사용
  • 바닥글 영역: v-footer 엘리먼트 사용
 <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900&display=swap|Material+icon"
      rel="stylesheet"
    />
    <!-- |Material+icon 아이콘 같이 사용하려면 기입 -->
    <link
      href="https://cdn.jsdelivr.net/npm/@mdi/font@6.x/css/materialdesignicons.min.css"
      rel="stylesheet"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css"
      rel="stylesheet"
    />
    <title>vuetify practice</title>
      </head>
  <body>
    <div id="app">
      <!-- 첫화면의 시작은 v-app엘리먼트 사용 -->
      <v-app>
        <!-- 상당부분은 v-app-bar 엘리먼트 사용 -->
        <v-app-bar app>
          <v-app-bar-nav-icon></v-app-bar-nav-icon>
          <v-toolbar-title>Header입니다</v-toolbar-title>
        </v-app-bar>
        <!-- 콘텐츠 부분은 v-main 엘리먼트 사용 -->
        <v-main>
          안녕하세요
          <v-container>Contents 입니다.</v-container>
        </v-main>
        <!-- 하단 부분은 v-footer 엘리먼트 사용 -->
        <v-footer>
          <div>Footer입니다.</div>
        </v-footer>
      </v-app>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
    <script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
    <script>
      new Vue({
        el: "#app",
        vuetify: new Vuetify(),
      });
    </script>
  </body>

- 03. 기본 레이아웃 만들기 2

구성요소 추가 및 스타일 적용

  • 틀바에 버튼 아이콘을 추가
  • 콘텐츠 영역에 타이포그래피 추가 및 스타일 적용
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900&display=swap|Material+icon"
      rel="stylesheet"
    />
    <!-- |Material+icon 아이콘 같이 사용하려면 기입 -->
    <link
      href="https://cdn.jsdelivr.net/npm/@mdi/font@6.x/css/materialdesignicons.min.css"
      rel="stylesheet"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css"
      rel="stylesheet"
    />
    <title>vuetify practice</title>
  </head>
  <body>
    <div id="app">
      <v-app>
        <!-- 앱바색상을 primary(파란색)로 설정하고 fixed로 위치 고정 -->
        <v-app-bar app color="primary" dark fixed>
          <v-app-bar-nav-icon></v-app-bar-nav-icon>
          <v-toolbar-title>마스터 페이지</v-toolbar-title>
          <!-- 우측에 추가메뉴 아이콘을 넣기 위해 v-spacer엘리먼트사용 -->
          <v-spacer></v-spacer>
          <v-btn icon>
            <v-icon>mdi-dots-vertical</v-icon>
          </v-btn>
        </v-app-bar>

        <v-main>
          <v-container>
            <!-- display-1/3, body-1/2 타이포그래피 서체 종류와 크기로 설정 -->
            <h1 class="display-1 my-5">안녕하세요</h1>
            <!-- my-4로 상하 안쪽여백 설정 -->
            <p class="body-2 my-4">마스터페이지입니다.</p>
            <v-divider></v-divider>
            <h1 class="display3 my-4">안녕하세요</h1>
            <p class="body-1 my-4">마스터페이지입니다.</p>
          </v-container>
        </v-main>
        <!-- footer 색상을 secondary로 설정하고 fixed로 위치를 고정 -->
        <v-footer color="secondary" dark fixed>
          <!-- mx-auto는 블럭레벨 엘리먼트의 내용을 가운데 정렬시킴 -->
          <div class="mx-auto">Copyright &copy;</div>
        </v-footer>
      </v-app>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
    <script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
    <script>
      new Vue({
        el: "#app",
        vuetify: new Vuetify(),
      });
    </script>

- 04. 카드 UI

카드 UI는 실전에서 상당히 많이 사용되는 UI 컴포넌트

  • v-card 엘리먼트로 카드 UI를 쉽게 구현
  • v-img와 v-card-title 엘리먼트로 이미지와 제목 작성
 <v-app>
        <!-- 앱바색상을 primary(파란색)로 설정하고 fixed로 위치 고정 -->
        <v-app-bar app color="primary" dark fixed>
          <v-app-bar-nav-icon></v-app-bar-nav-icon>
          <v-toolbar-title>마스터 페이지</v-toolbar-title>
          <!-- 우측에 추가메뉴 아이콘을 넣기 위해 v-spacer엘리먼트사용 -->
          <v-spacer></v-spacer>
          <v-btn icon>
            <v-icon>mdi-dots-vertical</v-icon>
          </v-btn>
        </v-app-bar>

        <v-main>
          <v-container>
            <!-- 카드 UI 사용을 선언하는 v-card 엘리먼트 -->
            <v-card max-width="400">
              <!-- 카드 상단에 이미지 배치 // aspect-ratio 는 비율 -->
              <v-img src="" aspect-ratio="2"></v-img>
              <!-- 카드 중간에 텍스트 배치 -->
              <v-card-text>
                <div>
                  <!-- 제목의 타이포그래피 스타일을 title로 설정 -->
                  <!-- 하단의 margin을 2로 설정 -->
                  <h2 class="title primary--text mb-2">카드UI</h2>
                  <p class="mb-0">카드 디자인에 출력될 텍스트를 입력합니다.</p>
                </div>
              </v-card-text>
              <!-- 카드 하단에 버튼 배치 -->
              <v-card-actions>
                <!-- 버튼 색상은 붉은 색으로 설정 -->
                <v-btn color="red white--text ">확인</v-btn>
                <!-- outline으로 버튼의 배경색 제거 -->
                <v-btn outlined color="red">취소</v-btn>
                <v-btn color="#9c27b0 dark">적용</v-btn>
              </v-card-actions>
            </v-card>
          </v-container>
        </v-main>

        <v-footer color="secondary" dark fixed>
          <div class="mx-auto">Copyright &copy;</div>
        </v-footer>
      </v-app>

- 05. 그리드 기본 원리

그리드는 화면 레이아웃 작업에서 가장 핵심

  • 반응형 웹 디자인을 하려면 그리드 사용법은 필수
  • v-row, v-col 엘리먼트를 통해 그리드 기능을 충실히 제공
 <v-app>
        <v-main>
          <v-container>
            <!-- 한 행은 12개의 열이 기준 -->
            <v-row class="text-center">
              <v-col cols="12" class="border_style">xs12</v-col>
              <v-col cols="6" class="border_style">xs6</v-col>
              <v-col cols="3" class="border_style">xs3</v-col>
              <!-- 현재 열의 개수가 9개인데 열 4개를 추가하면 12를 초과하므로 자동 줄바꿈 -->
              <v-col cols="4" class="border_style">xs4</v-col>
              <!-- 총 12개의 열을 추가 . 8개열을 채운 후 4개의 열은 자동으로 줄바꿈 -->
              <v-col
                cols="1"
                v-for="item in 12"
                v-bind:key="item.id"
                class="border_style"
                >xs1</v-col
              >
            </v-row>
            <br />
            <v-row class="text-center">
              <v-col
                cols="1"
                v-for="item in 20"
                v-bind:key="item.id"
                class="border_style"
              >
                xs1</v-col
              >
            </v-row>
          </v-container>
          <v-container fluid>
            <v-row class="text-center">
              <v-col cols="12" sm="4" class="border_style">sm4</v-col>
              <!-- offset으로 그리드 사이에 4개의 열 간격을 띄움 -->
              <v-col cols="12" sm="4" offset-sm="4" class="border_style"
                >4</v-col
              >
            </v-row>
          </v-container>
        </v-main>
      </v-app>

- 06. 반응형 그리드

반응형 웹 디자인을 그리드로 제작

  • 데스크톱 pc와 모바일 웹 디자인을 반응형으로 제작
<v-app>
        <v-app-bar app flat color="primary">
          <v-toolbar-title class="white--text mx-auto">
            화면 크기에 따른 레이아웃 변경
          </v-toolbar-title>
        </v-app-bar>

        <v-main>
          <v-container>
            <!-- 한 행은 12개의 열이 기준 -->
            <v-row>
              <!-- 첫번째 열의 반응형 크기를 지정 1. xs의 경우 : 12개의 열을 사용하여
              한 행을 모두 차지 2. sm의 경우 6개의 열을 사용하여 절반 너비를
              차지 -->
              <v-col cols="12" sm="6">
                <h2 class="mb-3">Content1</h2>
                <p>첫 번째 영역</p>
              </v-col>
              <!-- 두번째 열의 반응형 크기 지정
              1.xs의 경우 :12개의 열을 사용하여 한 행을 모두 차지
              2.sm의 경우 : 6개의 열을 사용하여 절반 너비를 차지 -->
              <v-col cols="12" sm="6">
                <h2 class="mb-3">Content1</h2>
                <p>두 번째 영역</p>
              </v-col>
            </v-row>
          </v-container>
        </v-main>
      </v-app>
728x90

'VueJS > VueJS' 카테고리의 다른 글

2023/06/19__VueJS(Vue && PWA && Firebase)  (0) 2023.06.20
2023/06/15__VueJS(vuetify)  (0) 2023.06.15
2023/06/13__VueJS(router)  (0) 2023.06.13
2023/06/12__Vue.JS(2) (computed, method, component, templet, Vuex)  (0) 2023.06.12
2023/06/09__Vue.js  (0) 2023.06.09
반응형

06.내비게이션과 라우터

라우터란?

  • 페이지 간 이동을 위한 라이브러리
  • 경로와 컴포넌트를 등록하면 싱글페이지 앱에서 사용자가 클릭한 경로로 화면이 이동하도록 도와줌

주요기능

  • 중첩된 route/view mapping
  • 모듈화된, 컴포넌트 기반의 라우터 설정
  • 라우터 파라미터, 쿼리, 와일드 카드
  • vue.js의 transition system을 이요한 트랜지션 효과
  • 세밀한(Fine-grained) 네비게이션 컨트롤
  • active CSS 클래스를 자동으로 추가해주는 링크
  • HTML5 History모드 또는 Hash 모드
  • -- auto-fallback in IE9
  • -- vue router에서 default는 Hash 모드
  • 사용자 정의 가능한 스크롤 동작

(네이티브 앱같은 분위기를 내려면 spa가 좋지만 검색엔진 같은 분위기로는 spa는 좋은 선택이 아닐 수도 있다.)

 <div id="app">
      <h1>안녕하세요</h1>
      <p>
        라우터사용
        <router-link to="/main">메인페이지</router-link>
        <router-link to="/sub">서브페이지</router-link>
      </p>
      <hr />
      <router-view></router-view>
    </div>
    <script>
      const tmMain = {
        template: `<h2>메인페이지</h2>`,
      };
      const tmSub = {
        template: `<h2>서브페이지</h2>`,
      };
      const rtRouter = [
        {
          path: "/main",
          component: tmMain,
        },
        {
          path: "/sub",
          component: tmSub,
        },
      ];
      //라우터 인스턴스를 생성하고 'routes'옵션을 전달
      // 'router'객체변수는 라우터 인스턴스이면서 Vue생성 시 옵션으로 사용되므로 변수 이름은 반드시 'router'사용
      const router = new VueRouter({
        routes: [...rtRouter],
      });

      // 뷰 루트 인스턴스를 만들고 router 옵션 추가
      const app = new Vue({
        el: "#app",
        router,
        //반드시 const router = new VueRouter({})에서 작성한 이름 사용
      });
    </script>

07. 새로 고침이 불피요한 SPA 만들기

싱글 페이지 앱(SPA, Single Page App)이란?

  • 서버에 매번 요청하더라도 새로고침이 불필요
  • 사용자의 서비스 경험속도가 훨씬 빨라짐 ex) 구글 지메일, 구글 맵, 페이스북, 트위터 등

router history mode는 주소표시줄에 #을 제거

728x90

'VueJS > VueJS' 카테고리의 다른 글

2023/06/19__VueJS(Vue && PWA && Firebase)  (0) 2023.06.20
2023/06/15__VueJS(vuetify)  (0) 2023.06.15
2023/06/14__VueJS(Vuetify)  (0) 2023.06.14
2023/06/12__Vue.JS(2) (computed, method, component, templet, Vuex)  (0) 2023.06.12
2023/06/09__Vue.js  (0) 2023.06.09
반응형

01. 복잡한 로직과 computed 속성

computed 속성

  • 머스태시를 이용해 HTML 엘리먼트 값이 어떠헥 변경되는지 살펴보면서 필요한 연산 작업을 도움
<div id="main">
      <p>원본 :"{{originMsg}}"</p>
      <p>대문자로 변환 :"{{upperCaseMsg}}"</p>
      <input type="text" v-model:value="upperInput" />
      <h2>{{upperInput}}</h2>
      <p>{{upperInputValue}}</p>
    </div>
    
    <script>
      let app = new Vue({
        el: "#main",
        data: {
          originMsg: "Hello, Vue Js",
          upperInput: "hi",
        },
        //computed는 mustache 안에 전달값이 자바스크립트 로직 등 복잡할 때 사용
        computed: {
          //originMsg의 데이터 값을 모두 대문자로 변환하여 반환
          //이 때 data의 값에 접근하기 위해 this 사용
          upperCaseMsg: function () {
            return this.originMsg.toUpperCase();
          },
          upperInputValue: function () {
            return this.upperInput.toUpperCase();
          },
        },
      });
    </script>

02. 이벤트 핸들러 로직과 method 속성

method 속성

  • 이벤트 핸들러를 사용해 마우스 클릭과 같은 이벤트가 발생했을 때 실행되는 로직에 활용
  • 메서드는 뷰 인스턴스에 포함해 사용하는 함수를 의미

computed 속성과 method 속성의 차이점

computed 속성

  • 머스태시에 작성할 로직이 복잡하면 함수로 정의할 때
  • 계산량이 많아 캐시가 필요할 때

methods속성

  • 뷰의 이벤트 핸들러 로직을 함수로 정의할 때
<div id="main2">
      <p>클릭숫자 : {{nClick}}</p>
      <p>카운트 다운 : {{fnCounter}}</p>
      <!-- 버튼을 누르면 fnIncrement 메서드 실행 -->
      <button v-on:click="fnIncrement">CLICK</button>
    </div>
    <script>
      new Vue({
        el: "#main2",
        data: {
          nClick: 0,
        },
        //메서드는 이벤트핸들러 로직을 실행할 때 사용
        methods: {
          fnIncrement() {
            if (this.fnCounter === 0) {
              return null;
            } else {
              this.nClick++;
            }
          },
        },
        //computed는 mustache 안에 로직이 복잡할 때 사용
        computed: {
          fnCounter() {
            //nClick값이 10을 기준으로 거꾸로 카운트 되도록 하나 감소시킴
            return 10 - this.nClick;
          },
        },
      });
    </script>

03. 컴포넌트로 HTML 엘리먼트 만들기

컴포넌트(component)란?

  • 뷰의 중요한 특징 중 하나이며 HTML의 기본 엘리먼트 외에 자신만의 엘리먼트를 만들어 쓰는 모듈을 의미
  • 미리 만든 컴포넌트 이름을 가지고 여는 태그(<>)와 닫는 태그(</>)에 적용해 사용

템플릿(template)이란?

  • 새로운 엘리먼트처럼 사용할 수 있도록 컴포넌트를 등록할 때 HTML과 뷰 코드로 작성된 소스를 의미

템플릿 속성

  • 컴포넌트 안에서 화면에 표시될 부분을 처리하는 속성
  • HTML, CSS, 자바스크립트를 적용하여 표시될 내용의 구조와 표현, 사요자와의 상화작용 기능을 구현
  • 백틱(`)키를 사용하여 문자열을 선언하면 줄바꿈이 있어도 HTML문서로 자동으로 인식
<div id="main3">
      <h1>{{sTitle}}</h1>
      <favorite-fruits></favorite-fruits>
      <favorite-fruits></favorite-fruits>
      <favorite-fruits></favorite-fruits>
    </div>
    
    //좋아하는 과일 3개를 표시하는 컴포넌트 정의
      Vue.component("favorite-fruits", {
        // 데이터는 fruits의 배열에 3개의 과일명을 반환하는 함수로 정의
        data: function () {
          return {
            fruits: [
              {fruit_name: "사과"},
              {fruit_name: "포도"},
              {fruit_name: "딸기"},
            ],
          };
        },
        // 템플릿은 화면에 표시할 엘리먼트 구조 정의
        template: `
        <div class="fruit_style">
            <div v-for="item in fruits">
                <p> 좋아하는 과일 :{{item.fruit_name}}</p>
                </div>
            </div>
        `,
      });
      new Vue({
        el: "#main3",
        data: {
          sTitle: "Hello",
        },
      });

04. 컴포넌트 속성 props

컴포넌트 속성(props)

  • 컴포넌트에서 전달되는 어트리뷰트의 값으로써, 문자열이나 객체의 배열 형식을 사용
  • <componet props="value"> </component>

뷰의 컴포넌트 장점

  • HTML의 일반 엘리먼트처럼 사용할 수 있기 때문에 기능을 무한대로 확장할 수 있는 잠재력
  • 다양한 주제별로 그에 맞는 엘리먼트를 설계하여 사용
  • 컴팩트한 개발이 가능하므로 유지보수 관점에서도 편리
<div id="app">
      <h1>{{sTitle}}</h1>
      <ol>
        <!-- favorite-fruits 신규 엘리먼트 사용
        fruits 배열의 값을 반복문으로 가져와 fruit 속성에 바인딩하여 컴포넌트에 전달 key 속성은 반드시 고유한 값으로 전달되어야 하믕로 item의 값 id값 대입 -->
        <favorite-fruits
          v-for="(item,index) in fruits"
          v-bind:fruit="item"
          :key="item.text"
        >
        </favorite-fruits>
      </ol>
    </div>
    <script>
      //Vue 인스턴스에 신규 엘리먼트 컴포넌트 등록
      //props에 엘리먼트에 사용될 속성 이름선언
      //tempalte에 전달받은 속성 객체의 text 값을 렌더링에 활용
      Vue.component("favorite-fruits", {
        props: ["fruit"],
        template: `<li>{{fruit.text}}</li>`,
      });
      new Vue({
        el: "#app",
        data: {
          sTitle: "Favorite fruits",
          //컴포넌트에 표시할 과일 데이터 정의
          fruits: [
            {id: 0, text: "사과"},
            {id: 1, text: "배"},
            {id: 2, text: "복숭아"},
          ],
        },
      });
    </script>

05.상태 관리와 Vuex

Vuex란?

  • 뷰의 코어 중 상태 관리를 위한 패터 & 라이브러리
  • 하나의 뷰 또는 복수의 화면 사이에서 여러 개의 컴포넌트를 사용하게 되면 각 컴포넌트 간에 상태값 전달이나 공유 (컴포넌트 간 공유할 수 있는 데이터 관리)
  • localStorage에 저장되지 않고 메모리에 저장되므로 새로고침 시 데이터 초기화
  • 상태를 새로고침 하더라도 데이터를 유지하기 위해서는 별도의 라이브러리 필요

Vuex의 작동 원리 이해하기

  • State, Mutations, Getters, Actions 4개의 속성
  • State : 공유한 상태값 데이터 정의
  • Mutations : setter의 의미, 외부에서 동기 방식으로 저장할 때 사용
  • Getters : state의 데이터 값을 외부에서 읽어 올 때 사용
  • Actions : 외부의 API 실행 같은 비동기 실행을 관리할 때 사용
<div id="app">
      <h1>안녕하세요</h1>
      <!-- 카운터 신규 엘림너트 2개 사용. msg 속성에 이름만 다르게 적용 -->
      <com-counter msg="count1"></com-counter>
      <com-counter msg="count2"></com-counter>
    </div>
    <script>
      //Vuex의 store 중앙에 state,mutaions(setters), getters, actions을 정의함
      const store = new Vuex.Store({
        //count 값을 상탱 값으로 정의
        state: {
          count: 0,
        },
        //mutations는 getters의 대칭되는 setters의 역할을 설정
        // 데이터 변경
        mutations: {
          fnIncData: function (state) {
            return state.count++;
          }, //화샃표 함수를 활용해 count 상태값을 감소하도록 정의
          fnDecData: (state) => {
            state.count--;
          },
        },
        getters: {
          //상태값을 반환함
          fnGetData(state) {
            return state.count;
          },
        },
        actions: {
          //외부데이터 사용도 여기서 할것이다.
          //상태값을 감소시키는 함수를 서버단에서 실행한다고 가정
          //비동기 실행을 위해 async를 사용하고 매개변수로 commit객체 전달
          async fnDecData({commit}, state) {
            //가상으로 마든 원격 api 실행}
            const result = await api.fnDecrement();
            //원격 api가 성공할 경웨 비로소 fnDerData 함수 실행
            if (result == true) commit("fnDecData");
          },
        },
        //타이머를 사용해 1초 후 true값을 반환하도록 가상 원격 서버 API 정의
      });
      const api = {
        //외부데이터의 모습 예졔
        fnDecrement() {
          //비동기 계산을 수행하기 위해 Promise를 사용하고 그에 따른 성공값을 반환하기 위해 resolve 함수 실행
          return new Promise((resolve) => {
            setTimeout(() => {
              resolve(true);
            }, 0);
          });
        },
      };
      Vue.component("com-counter", {
        //카운터 제목은 엘리먼트의 msg 속성값을 받아서 렌더링 함
        props: ["msg"],
        template: `
        <div>
            <h2>{{msg}}</h2>
            <p>카운터 : {{fnGetCount}}</p>
            <button type="button" @click='fnIncCount'>+ 1증가</button>
            <button type="button" @click='fnDecCount'> - 1 감소(원격 Api 실행)</button>
            <hr/>
            </div>
        `,
        computed: {
          //카운터 값은 store에서 getters에 접근하여 값을 가져온 후 렌더링 함
          fnGetCount() {
            return store.getters.fnGetData;
          },
        },
        methods: {
          //카운터 증가는 동기실행을 가정하고 직접 store의 mutations에 접근 하여 실행
          fnIncCount() {
            store.commit("fnIncData");
          },
          //카운터 감소는 원격 서버 API로 비동기 실행을 가정하고 actions에 접근하여 실행
          fnDecCount() {
            store.dispatch("fnDecData");
          },
        },
      });
      const app = new Vue({
        el: "#app",
        //store 사용을 선언함
        store,
      });
    </script>
728x90

'VueJS > VueJS' 카테고리의 다른 글

2023/06/19__VueJS(Vue && PWA && Firebase)  (0) 2023.06.20
2023/06/15__VueJS(vuetify)  (0) 2023.06.15
2023/06/14__VueJS(Vuetify)  (0) 2023.06.14
2023/06/13__VueJS(router)  (0) 2023.06.13
2023/06/09__Vue.js  (0) 2023.06.09
반응형

뷰(Vue.js)란?

  • 2013년 구글의 개발장였던 에반 유(Evan You)에 의해 출시
  • 인터렉티브 웹 인터페이스를 개발하기 위한 '프로그레시브 자바스크립트 프레임워크'
  • 웹에서 UI 뷰, 비즈니스 로직, 데이터의 관리를 돕는 최고 성능의 컴팩트한 자바스크립트 라이브러리.

 

리액트는 그룹단위 / 뷰는 개인단위 가 이상적

 

Vue.js가 주목 받는 4가지 이유

  1. 디자이너와 개발자를 위해 쉽게 설계되었다.
  2. MVC(model view controller) 모델을 지원한다.
  3. HTML5와 자바스크립트만 알면 되므로 쉽게 시작할 수 있다.
  4. 설치하기 쉽고 용량이 작아서 속도가 빠르다.

 

Vue 프레임워크의 특징

  • Vuie.js 출발은 가장 늦었지만 다른 프레임워크들의 단점을 보완해 성능이 우수
  • 사용성이 매우 뛰어난데 이런 강점을 중심으로 지속적으로 발전

기쁘게 참여하는 커뮤니티 문화

  • 신선한 아이디어로 개발을 즐겁고 자유롭게 할 수 있는 커뮤니티 중심

bestofjs.org

  • 다양한 관점으로 기술 추이를 분석하여 순위
  • 최근 통계를 보면 인기도면에서 뷰가 1등을 차지했었음

 -- Vue.js , Hello World!

뷰의 기본 사용법과 특징

  • cdn으로 설정하는 방법
  • 머스태시라고 불리는  {{}} 활용법
  • data 속성의 바인딩 관계를 이해

data 속성

data 속성은 뷰 안에서 사용할 데이터를 변수명으로 선언하여 관리하는 곳

객체나 함수를 선언하여 데이터를 일고 저장하는 일 수행

    <div id="app">
      <!-- sTitle 값을 받아서 HTML의 엘리먼트 값으로 변환하여 표시함 -->
      <p>{{sTitle}}</p>
      <!-- {{}} 사용 -->
    </div>
js
  new Vue({
        el: "#app",
		data:{
		//{{sTitle}}로 데이터 값을 전달함
			sTitle:'Hello ,World!' // 문자도 올수도 있고 함수도 올수 있다.
			},
         method:{
         //간단한 데이터는 method로 보낼 수 있다.
         }
         
		})

단방향 바인딩과 v-bind디렉티브

데이터 바인딩

  • HTML의 어트리뷰트(attribute)값을 수정할 때 v-bind라는 디렉티브를 이용해서 데이터 값을 브라우저 화면에 자동으로 반영하는 것을 의미
  • 변수값을 HTML어트리뷰트에 연결함으로써 변수가 새로운 값으로 바뀔 때마다 HTML엘리먼트에 실시간으로 렌더링
  • 양방향으로는 v-model

v-bind 디렉티브

  • 콜론(:)을 중심으로 왼쪽에는 v-bind를 기입하고, 오른쪽에는 HTML엘리먼트의 어트리뷰트를 선언해서 바인딩으로 만들어진 값을 대입하는 식
  • 콜론(:)만 사용하면 v-bind라는 명칭은 생략

양방향 바인딩과 v-model 디렉티브

양방향 데이터 바인딩

  • 입력과 동시에 데이터가 동기화되어 표시되는 기능을 수행

v-model 디렉티브

  • HTML어트리뷰트에 양방향 데이터 바인딩을 수행
  • 콜론(:)을 중심으로 왼쪽에는 v-model을 기입하고 오른쪽에는 HTML 엘리먼트의 어트리뷰트 이름을 작성

v-bind디렉티브

  • sDate값을 HTML어트리뷰트에 보내기만 함
<input v-bind:value="sDate"/>

v-model디렉티브

  • sMsg값과 입력값이 서로 연동됨
<input v-model:value="sMsg"/>

v-if 디렉티브

  • 조건이 충족될 때만 렌더링을 수행하도록 돕는 어트리뷰트
<!-- v-if,else로 직접 bFlag 데이터에 접근하여 조건 판단 -->
      <p v-if="bFlag ==true">앞면!</p>
      <p v-else>뒷면</p>

v-for

  • HTML 안에서 반복문으로 배열값을 읽어서 목록의 항목과 인덱스 변수에 저장하도록 돕는 어트리뷰트
  <h1>좋아하는 과일 리스트</h1>
      <!-- v-for반복문으로 fruits과일 배열 데이터를 가져옴 -->
      <ol>
        <li v-for="item in fruits">
          <!-- fruits 안의 fruitsName항목을 하나씩 가져와 html로 렌더링 -->
          {{item.fruitName}}
        </li>
      </ol>

v-on 디렉티브

  • 뷰에서 발생하는 이벤트를 지켜보면서 DOM엘리먼트를 제어할 수 있도록 도와주는 어트리뷰트
  • 뷰 안에서 사용자가 키보드나 마우스를 제어하는 형식의 이벤트가 발생했을 때 이를 실행하는 함수와 바인딩 할 때 사용

-- 이벤트 핸들러

  • 이벤트가 발생했을 때 실행되는 함수

-- 메소드(Methods)

  • 이벤트 핸들러 함수를 제작해야 할 때 미리 정의해 두고 사용
  • 뷰 객체의 행위를 정의하는 용도, 즉 로직을 실행하는 함수가 필요할 때 이곳에 정의해 두고 사용
methods :{
		//버튼을 눌렀을 때 sTitle의 제목 변경
	fnChangeTitle(){
		//this:Vue 객체의 인스턴스
	this.sTitle = 'hello!'
}

///////////////////
<input type="text" :value="inputValue" />
      <h3>{{inputValue}}</h3>
      <button type="button" v-on:click="plusClick">Click</button>
      
      new Vue({
        el: "#app2",
        data: {
          inputValue: 0,
        },
        methods: {
          plusClick() {
            this.inputValue = this.inputValue + 1;
          },
        },
      });
728x90

+ Recent posts