공부리뷰 16주차

전재우·2021년 5월 16일
0
post-thumbnail

2021-05-16

VUE는 MVC 모델에서 V에 해당한다

VUEMVVM (model, view, view model)모델로 생성한다.

M (js,logic) - data

VM(vue객체,vue 인스턴스) - "반응성" ,"상호 관련"

V(html) 화면

DOM(Document Object Model)

DOM은 HTML 문서에 대한 인터페이스입니다. 첫째로 뷰 포트에 무엇을 렌더링 할지 결정하기 위해 사용되며,둘째로는 페이지의 콘텐츠 및 구조, 그리고 스타일이 자바스크립트 프로그램에 의해 수정되기 위해 사용됩니다.DOM은 원본 HTML 문서 형태와 비슷하지만 몇 가지 차이점이 있습니다.

  • 항상 유효한 HTML 형식입니다.
  • 자바스크립트에 수정될 수 있는 동적 모델이어야 합니다.
  • 가상 요소를 포함하지 않습니다. (Ex. ::after)
  • 보이지 않는 요소를 포함합니다. (Ex. display: none)

MVVM Pattern

= Model + View + ViewModel

  • Model : 순수 자바스크립트 객체

  • View : 웹페이지 DOM(Document Object Model)

  • ViewModel : Vue의 역할

    기존에는 자바스크립트로 view에 해당하는 DOM에 접근하거나 수정하기 위해 Jquery와 같은 Library이용

    VueViewmodel을 연결하고 자동으로 바인딩하므로 양방향 통신이 가능함.

Vue life cycle

Vue 인스턴스나 컴포넌트가 생성될 때, 미리 사전에 정의된 몇 단계의 과정을 거치게 되는데 이를 라이프사이클(lifecycle)이라 합니다.

다시 말해, Vue 인스턴스가 생성된 후 우리 눈에 보여지고, 사라지기까지의 단계를 일컫는 말입니다.

  • Vue 인스턴스는 크게 생성(create)되고, DOM에 부착(mount)되고, 업데이트(update)되며, 없어지는(destroy) 4가지 과정을 거치게 됩니다
var app = new Vue({
    el: '#app',
    data() {
        return {
            msg: 'hello';
        }
    },
	//라이프사이클단계가들어가는곳
		beforeCreate(function() {
        console.log(this.msg); // undefined
    })
})

beforeCreate

Vue 인스턴스가 초기화 된 직후에 발생됩니다. 컴포넌트DOM에 추가되기도 전이어서 this.$el에 접근할 수 없습니다. 또한 data, event, watcher에도 접근하기 전이라 data, methods에도 접근할 수 없습니다.

created

created훅에서는 data를 반응형으로 추적할 수 있게 되며 computed, methods, watch 등이 활성화되어 접근이 가능하게 됩니다. 하지만 아직까지 DOM에는 추가되지 않은 상태입니다.

data에 직접 접근이 가능하기 때문에, 컴포넌트 초기에 외부에서 받아온 값들로 data를 세팅해야 하거나 이벤트 리스너를 선언해야 한다면 이 단계에서 하는 것이 가장 적절합니다.

beforeMount

DOM에 부착하기 직전에 호출되는 beforeMount훅입니다. 이 단계 전에서 템플릿이 있는지 없는지 확인한 후 템플릿을 렌더링 한 상태이므로, 가상 DOM이 생성되어 있으나 실제 DOM에 부착되지는 않은 상태입니다.

mounted

일반적으로 가장 많이 사용하는 mounted훅입니다. 가상 DOM의 내용이 실제 DOM에 부착되고 난 이후에 실행되므로, this.$el을 비롯한 data, computed, methods, watch 등 모든 요소에 접근이 가능합니다.

beforeUpdate

컴포넌트에서 사용되는 data의 값이 변해서, DOM에도 그 변화를 적용시켜야 할 때가 있습니다. 이 때, 변화 직전에 호출되는 것이 바로 beforeUpdate훅입니다. 변할 값을 이용해 가상 DOM을 렌더링하기 전이지만, 이 값을 이용해 작업할 수는 있습니다. 이 훅에서 값들을 추가적으로 변화시키더라도 랜더링을 추가로 호출하지는 않습니다.

updated

가상 DOM을 렌더링 하고 실제 DOM이 변경된 이후에 호출되는 updated훅입니다. 변경된 dataDOM에도 적용된 상태입니다. 만약 변경된 값들을 DOM을 이용해 접근하고 싶다면, updated훅이 가장 적절합니다.

다만 이 훅에서 data를 변경하는 것은 무한 루프를 일으킬 수 있으므로 이 훅에서는 데이터를 직접 바꾸어서는 안됩니다.

mounted훅과 마찬가지로, this.$nextTick을 이용해, 모든 화면이 업데이트 된 이후의 상태를 보장할 수 있습니다.

beforeDestroy

해당 인스턴스가 해체되기 직전에 beforeDestroy훅이 호출됩니다. 아직 해체되기 이전이므로, 인스턴스는 완전하게 작동하기 때문에 모든 속성에 접근이 가능합니다. 이 단계에서는 이벤트 리스너를 해제하는 등 인스턴스가 사라지기 전에 해야할 일들을 처리하면 됩니다.

destroyed

인스턴스가 해체되고 난 직후에 destroyed훅이 호출됩니다. 해체가 끝난 이후기 때문에, 인스턴스의 속성에 접근할 수 없습니다. 또한 하위 Vue 인스턴스 역시 삭제됩니다.

보간법 (Interpolation)

  • 데이터 바인딩의 가장 기본 형태는 Mustache 구문(이중 중괄호) 를 사용한 텍스트 보간
  • {{ 속성명 }}
  • v - once 디렉티브를 사용하여 데이터 변경 시 업데이트 되지 않는 일회성 보간을 수행

디렉티브 (Directives)

  • 디렉티브는 v-접두사가 있는 특수 속성

  • 디렉티브 속성 값은 단일 javaScript 표현식이 된다 . (V-for는 예외 )

  • 디렉티브의 역할은 표현식의 값이 변결될 때 사이드 이펙트를 반응적으로 DOM에 적용

  • v-mode

    양방향 바인딩을 처리

    • code
  • v-bind

    엘리먼트의 속성과 바인딩 처리를 위해서 사용

    • code
  • v-show

    조건에 따라 엘리먼트를 화면에 렌더링

    style의 display를 변경

    • code

      <body>
          <div id="app">
              <div v-show="isShow">{{msg}}</div>
          </div>
          <script>
              new Vue({
                  el: '#app',
                  data: {
                      isShow: true,
                      msg: '보이나요?'
                  }
              });
          </script>
      </body>
  • V-if, v-else, v-else if

    • 조건에 따라 엘리먼트를 화면에 렌더링

    • 조건이 다르면 아예 읽어 오지를 않는다.

    • code

      <body>
          <div id="app">
            <div>
              <span>나이 : </span>
              <input type="number" v-model="age" />
            </div>
            <div>
              요금 :
              <span v-if="age < 10">무료</span>
              <span v-else-if="age < 20">7000</span>
              <span v-else-if="age < 65">10000</span>
              <span v-else>3000</span>
            </div>
          </div>
          <script>
            const vm = new Vue({
              el: '#app',
              data: {
                age: '0',
              },
            });
          </script>
        </body>
  • v-show VS v-if

    v-if : 조건에 해당되지않으면 코드 상으로 아예 존재하지 않음

    v-show : false이면 코드론 있지만 화면엔 안 보이는 것

  • v-for

    배열이나 객체의 반복에 사용

    V-for = "요소변수이름 in 배열" V-for="(요소변수이름,인덱스) in 배열"

    • code
  • template

    여러 개의 태그들을 묶어서 처리해야 할 경우 Template를 사용

    v-if, v-for ,component 등과 많이 사용

Vue method

  • Vue instance는 생성과 관련된 data및 method 정의 가능

  • method 안에서 data를 this.데이터이름으로 접근가능

  • Code

    <body>
        <div id="app">
            <div>data : {{message}}</div>
            <div>method kor : {{helloKor()}}</div>
            <div>method eng : {{helloEng()}}</div>
        </div>
        <script>
            new Vue({
                el: "#app",
                data: {
                    message: "Hello ",
                    name: "전재우"
                },
                methods: {
                    helloEng() {
                        return "Hello " + this.name
                    },
                    helloKor() {
                        return "안녕 " + this.name
                    }
                }
            })
        </script>
    </body>

Vue Filter

  • filter를 이용하여 표현식에 새로운 결과 형식을 적용
  • 중괄호 보간법 [{{}}] 또는 v-bind 속성에서 사용이 가능
  • 천단위마다 " , " 찍기 , 전화 번호에 ' - ' 넣기

Vue Computed 속성

  • 특정 데이터의 변경사항을 실시간으로 처리

  • 캐싱을 이용하여 데이터의 변경이 없을 경우 캐싱된 데이터를 반환

  • setter와 getter를 직접 지정 할 수 있음

  • 작성은 Method 형태로 작성하지만 Vue에서 proxy 처리하여 property처럼 사용

  • code

    <body>
        <div id="app">
          <input type="text" v-model="message" />
          <p>원본 메시지: "{{ message }}"</p>
          <p>역순으로 표시한 메시지1: "{{ reversedMsg }}"</p>
          <p>역순으로 표시한 메시지2: "{{ reversedMsg }}"</p>
          <p>역순으로 표시한 메시지3: "{{ reversedMsg }}"</p>
        </div>
        <script>
          var vm = new Vue({
            el: '#app',
            data: {
              message: '안녕하세요 여러분',
            },
            computed: {
              reversedMsg: function () {
                console.log('꺼꾸로 찍기');
                return this.message.split('').reverse().join('');
              },
            },
          });
        </script>
      </body>

computed 속성은 Vue 인스턴스가 생성될 때 , data의 message 값을 받아 reversedMsg를 계산하여 저장해 놓는다. ( 변수에 값을 저장해놓는다고 생각 → 변경이 발생하면 변수에 변경된 데이터를 저장)

method로 구성하게 되면 reveresedMsg()를 사용하려고 할때 마다 계산한다.

Vue watch 속성

  • vue instance의 특정 property가 변경될 때 실행할 콜백 함수 설정
  • watch 데이터 변화를 감지하여 자동으로 특정 로직을 수행
  • computed와 비슷하지만 ( computed는 내장 API를 사용해서 실행 -> 간단한 연산 등에 적합!)
  • watch는 시간이 오래 걸리는 작업등에 적합 ( 비동기 요청 ! )
  • function 형식, 감시할 데이터 이름 으로 함수명 정하기 !!!
  • code

Vue Event

  • DOM Event를 청취하기 위해 v-on directive사용

  • inline event handling

  • method를 이용한 event handling

  • v-on :

    v-on directive를 사용하여 DOM이벤트를 듣고 트리거 될 때 javaScript를 실행할 수 있다.

  • method event handler

    이벤트 발생시 처리 로직을 v-on에 넣기 힘들다. 이 때문에 v-oon에서는 이벤트 발생시 처리해야 하는 method의 이름을 받아 처리( 복잡한 일을 수행할때는 함수를 이용하세요)

    • code

      <body>
          <div id="app">
            <button v-on:click="greet">Greet</button>
          </div>
          <script>
            var vm = new Vue({
              el: '#app',
              data: {
                name: 'SSAFY',
              },
              methods: {
                greet: function (event) {
                  alert('Hello ' + this.name + '!');
                  console.dir(event.target);
                },
              },
            });
      
            // 또한 JavaScript를 이용해서 메소드를 호출할 수 있습니다.
            //vm.greet(); // => 'Hello Vue.js!'
          </script>
        </body>
  • inline method handler

    메소드 이름을 직접 바인딩 하는 대신 인라인 javaScript 구문에 메소드를 사용할 수 잇다.

    원본 DOM이벤트에 액세스 해야하는 경우 특별한 $event 변수를 사용해 메소드에 전달할 수 있다.

    button의 default는 submit이다

    • code

      <body>
          <div id="app">
            <button v-on:click="greet1('jeus')">Greet</button>
            <button v-on:click="greet2($event, 'jeus')">Greet</button>
          </div>
          <script>
            new Vue({
              el: '#app',
              methods: {
                greet1: function (msg) {
                  alert('Hello ' + msg + '!');
                  console.dir(event.target);
                },
                greet2: function (e, msg) {
                  if (e) e.preventDefault();
                  alert('Hello ' + msg + '!');
                  console.dir(e.target);
                },
              },
            });
          </script>
        </body>
  • 이벤트 수식서

    • event.preventDefault()와 같이 method 내에서 작업할 수도 있지만 method는 DOM의 이벤트를 처리하는것보다 data처리를 위한 로직만 작업하는 것이 좋다.
    • 이 문제를 해결하기 위해서 VUE는 v-on 이벤트에 이벤트 수식어를 제공한다.
    • 수식어는 점으로 표시된 접미사 이다.
  • KEY 수식어

    • VUE는 키 이벤트를 수신할 때 V-on에 대한 키 수식어를 추가할 수 있다.
    • code
  • ref, $refs

    뷰에서는 $refs속성을 이용해 DOM에 접근 할 수 있다.

    단, VUE의 가장 중요한 목적 중 하나는 개발자가 DOM을 다루지 않게 하는것이므로 , 되도록 ref를 사용하는 것을 피하는 것이 좋다.

    • code

Class Binding

  • Element의 class와 style을 변경
  • v-bind : class 조건에 따라 class를 적용할 수 있다.
  • code

폼 입력 바인딩 (Form Input Bindings)

V - model directive를 사용하여 폼 input과 textarea element에 양방향 데이터 바인딩을 생성할 수 있다.

text 와 textarea 태그는 value 속성과 input 이벤트를 사용한다.

체크박스들과 라디오버튼들은 checked 속성과 change 이벤트를 사용한다

select 태그는 value를 prop으로 change를 이벤트로 사용한다.

  • code

  • check box

    <body>
        <div id="app">
          <div>
            <p>
              이메일 수신
              <input type="checkbox" id="emailYN" v-model="email" />
              <label for="emailYN">{{ email }}</label>
            </p>
          </div>
          <div>
            <p>
              SMS 수신
              <input type="checkbox" id="smsYN" v-model="sms" true-value="Y" false-value="N" />
              <label for="smsYN">{{ sms }}</label>
            </p>
          </div>
        </div>
        <script>
          new Vue({
            el: '#app',
            data: {
              email: false,
              sms: 'Y',
            },
          });
        </script>
      </body>

V-model은 양방향 통신

컴포넌트 (Component)

  • Vue의 가장 강력한 기능 중 하나
  • HTML Element를 확장하여 재사용 가능한 코드를 캡슐화
  • Vue Component는 Vue Instance 이기도 하기 때문에 모든 옵션 객체를 사용
  • Life Cycle Hook 사용 가능
  • 전역 컴포넌트와 지역 컴포넌트

이름 표기법

컴포넌트 이름을 지을 때는 두 가지 방법이 있습니다.

케밥-표기법

Vue.component('my-component-name', { /* ... */ })

케밥-표기법으로 컴포넌트를 정의할 때는 사용자 정의 엘리먼트를 부를 때에도 <my-component-name>와 같이 반드시 케밥-표기법을 사용해야 합니다.

파스칼표기법

Vue.component('MyComponentName', { /* ... */ })

파스칼표기법으로 컴포넌트를 정의할 때는 사용자 정의 엘리먼트를 부를 때 두 가지 표기법 모두 사용할 수 있습니다. 즉 <my-component-name>와 <MyComponentName> 모두 괜찮습니다. 단, DOM에 바로 쓸 때는 케밥-표기법 이름만 가능합니다.

참고 : https://kr.vuejs.org/v2/style-guide/index.html

전역 컴포넌트

전역 컴포넌트를 등록하려면 Vue.component(tagName, options)를 사용

권장하는 컴포넌트 이름 : 케밥 표기법 ( 전부 소문자 )

<body>
    <div id="app1">
      <my-global></my-global>
      <my-global></my-global>
    </div>
    <div id="app2">
      <my-global></my-global>
      <my-global></my-global>
    </div>
    <script>
      Vue.component('MyGlobal', {
        template: '<h2>전역 컴포넌트임</h2>',
      });
      new Vue({
        el: '#app1',
      });
      new Vue({
        el: '#app2',
      });
    </script>
  </body>

지역 컴포넌트

<body>
    <div id="app1">
      <my-local></my-local>
      <my-local></my-local>
    </div>
    <div id="app2">
      <my-local></my-local>
      <my-local></my-local>
    </div>
    <script>
      new Vue({
        el: '#app1',
        components: {
          'my-local': {
            template: '<h2>지역 컴포넌트</h2>',
          },
        },
      });
      new Vue({
        el: '#app2',
      });
    </script>
  </body>

컴포넌트간 통신

  • 상위(부모) - 하위 (자식) 컴포넌트 간의 data 전달 방법
  • 부모에서 자식 : props(데이터)라는 특별한 속성을 전달
  • 자식에서 부모 : event로만 전달가능

  • 상위에서 하위 컴포넌트로 Data 전달

    하위 컴포넌트는 상위 컴포넌트의 값을 직접 참조 불가능

    data와 마찬가지로 props 속성 값을 template에서 사용이 가능

  • props

<body>
    <div id="app">
      <child-comp area="광주" v-bind:msg="msg[parseInt(Math.random() * 4)]"></child-comp>
      <child-comp area="구미" v-bind:msg="msg[parseInt(Math.random() * 4)]"></child-comp>
      <child-comp area="대전" v-bind:msg="msg[parseInt(Math.random() * 4)]"></child-comp>
      <child-comp area="서울" v-bind:msg="msg[parseInt(Math.random() * 4)]"></child-comp>
    </div>
    <template id="ChildComp">
      <div>
        <h2>SSAFY {{area}}지역 5{{msg}}</h2>
      </div>
    </template>
    <script>
      Vue.component('child-comp', {
        props: ['area', 'msg'],
        template: '#ChildComp',
      });
      new Vue({
        el: '#app',
        data: {
          msg: ['굿^^', '최고!!', '실화냐?', '좋아요*'],
        },
      });
    </script>
  </body>

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/06359141-50f5-4ee4-b386-47e01569f9b1/Untitled.png

사용자 정의 이벤트 (Custom Events)

  • 이벤트 이름
    • 컴포넌트 및 props와 달리 , 이벤트는 자동 대소문자 변환을 제공하지 않는다.
    • 대소문자를 혼용하는 대신에 emit할 정확한 이벤트 이름을 작성하는 것을 권장
    • v-on 이벤트 리스너는 항상 자동으로 소문자 변환 되기 때문에 v-on:myEvent는 자동으로 v-on:myevent로 변환된다. 이름이 my -event인 경우 myEvent 이벤트를 들을 수 없다.
    • 이러한 이유 때문에 , 이벤트 이름에는 케밥-케이스를 사용하는것이 권장됨
  • 이벤트 발생
    • vm.$emit("이벤트명",[...파라미터]);
  • 이벤트 수신
    • vm.$on("이벤트명",콜백함수(){});

하위에서 상위 컴포넌트로 event 전달

  • 하위 컴포넌트에서 상위 컴포넌트가 지정한 이벤트를 발생 $emit
  • 상위 컴포넌트는 하위 컴포넌트가 발생한 이벤트를 수신 (on)하여 data처리
<body>
		<div id="app">
			<input type="text" v-model="num" />
			<child-compo @help="parentMethod(num)" :message="msg"></child-compo>
		</div>
		<script>
			//global component
			Vue.component("child-compo", {
				template: "<button @click='send'>{{message}}</button>",

				props: ["message"], //부모로부터 받아올 데이터, 자식이 가지는 속성명 12번째 줄

				methods: {
					send() {
						console.log("child-compo");
						this.$emit("help"); //이벤트를 발생시키는 문장
					},
				},
			});
			var vm = new Vue({
				el: "#app",
				data: {
					//부모가 자식에게 전달할 데이터
					msg: "부모의 데이터다!",
					num: 0,
				},
				methods: {
					parentMethod(val) {
						console.log("자식에게서 받은 데이터 : " + val);
					},
				},
			});
		</script>
	</body>

비 상하위간 통신

  • 비어있는 vue instance 객체를 event bus로 사용
  • 복잡해질 경우 상태관리 라이브러리인 Vuex 사용 권장
  • event 버스 사용 코드
<body>
		<template id="up">
			<div>
				<input type="number" v-model="ucount" @keyup.enter="send" />
			</div>
		</template>
		<template id="down">
			<div>
				<h2>{{dcount}}</h2>
			</div>
		</template>
		<div id="app">
			<h1>Event Bus Test</h1>
			<up-area></up-area>
			<hr />
			<down-area></down-area>
		</div>
		<script>
			//eventBus 역할의 객체
			//컴포넌트 중에서 이벤트 발생시키면 받고, 보내주는 역할
			var bus = new Vue();
			//데이터를 보내는 (event가 발생되는 쪽 ) bus.$emit
			Vue.component("up-area", {
				template: "#up",
				data() {
					return {
						ucount: 0,
					};
				},
				methods: {
					send() {
						//down-area 쪽으로 데이터를 보내기 -> 이벤트 발생
						bus.$emit("updateDown", this.ucount);
						this.ucount = "";
					},
				},
			});

			//데이터를 받는 (event를 받는 )쪽 : bus.$on
			Vue.component("down-area", {
				template: "#down",
				data() {
					return {
						dcount: 0,
					};
				},
				created: function () {
					//"down-area" 컴포넌트가 만들어 지고 나서
					//bus.$on("updateDown", this.updateLog);
					bus.$on("updateDown", (value) => {
						this.dcount += value;
					});
				},
				methods: {
					updateLog(value) {
						this.dcount += value;
					},
				},
			});
			var vm = new Vue({
				el: "#app",
			});
		</script>
	</body>

AXIOS

axios는 Model과 데이터를 주고받는 용도 (REST 방식)

Vue에서 권고하는 http 통신 라이브러리는 AXIOS이다

Promise 기반의 HTTP 통신 라이브러리이며 상대적으로 다른 HTTP 통신 라이브러리들에 비해 문서화가 잘 되 어 있고 API가 다양한다.

<body>
		<div id="app">
			<div id="result">
				<table>
					<tr>
						<th>글번호</th>
						<th>제목</th>
						<th>작성자</th>
						<th>작성일</th>
					</tr>
					<tr v-for="article in articles">
						<td>{{article.no}}</td>
						<td>{{article.title}}</td>
						<td>{{article.writer}}</td>
						<td>{{article.regtime}}</td>
					</tr>
				</table>
			</div>
		</div>
		<script>
			const addr = "http://localhost:9999/vue/api/board";

			new Vue({
				el: "#app",
				data: {
					articles: [],
				},
				created() {
					axios
						.get(addr) //요청
						.then((response) => {
							this.articles = response.data;
						})
						.catch((error) => {
							console.dir(error);
						});

					axios.get(url).then().catch;
					axios
						.post(url, {})
						.then((response) => {
							//response : 서버에서 오는 응답 정보
							response.data;
						})
						.catch((response) => {
							response.status;
						});
				},
			});
		</script>
	</body>

Vue-Router

NPM ( Maven)

  • NPM 명령어

    npm init : 새로운 프로젝트나 패키지를 만들때 사용 (package.json)이 생성됨

    npm install package : 생성되는 위치에서만 사용 가능한 패키지로 설치

    npm install -g package : 글로벌 패키지에 추가 , 모든 프로젝트에서 사용 가능한 패키지로 설치

vue/cli\

Vue CLI는 애플리케이션에 필요한 요소들을 대화형 커맨드로 쉽게 설치하도록 도와준다. 현재 Vue CLI는 3.x까지 릴리즈된 상태이며, Vue CLI의 시스템은 3가지 요소로 구분할 수 있다.

  • CLI - Command Line Interface
profile
코린이

0개의 댓글