반응형

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

+ Recent posts