BeNI 2022. 11. 30. 18:14
728x90

 


📘 Vue 란?

: 사용자 인터페이스를 구축하기 위한 JavaScript 프레임워크 중 하나

  • 선언적 렌더링(Declarative Rendering): Vue는 표준 HTML에서 JavaScript 상태(State)를 기반으로 화면에 출력될 HTML을 선언적으로 작성 가능
  • 반응성(Reactivity): 상태가 변경되면 DOM(화면)을 가상 DOM을 이용하여 효율적으로 업데이트함

 

 

1. 시작하기 

- 본 강의에서는 CDN을 사용하였다.

<script src="https://unpkg.com/vue@3"></script>

 

1) 기본 문법

<div id="app">{{ message }}</div>

<script>
  const { createApp } = Vue;

  const app = createApp({
    data() {
      return {
        message: 'Hello Vue!'
      }
    }
  };
  app.mount('#app')
</script>

✅ createApp()

- data는 Vue의 인스턴스가 사용할 정보를 담고있는 속성으로 객체/함수 형태이다.

- 위 예제에서는 message라는 변수를 선언했다.

 

✅ mount()

- 앱 인스턴스를 렌더링한다.

- mount()가 실행되기 전까진 아무것도 렌더링 되지 않는다. 

 

✅ {{ }} (이중 괄호)

- data에서 선언했던 데이터들을 이중 괄호 형태로 선언하여 화면에 출력한다.

 

 

2) 템플릿 문법

: Vue는 컴포넌트 인스턴스의 데이터를 DOM에 바인딩할 수 있는 HTML 기반 템플릿 문법을 사용한다.

 

ⓐ 텍스트 보간법

- 가장 기본적인 형태로 이중 중괄호 문법을 이용한다.

<span>메세지: {{ msg }}</span>

- 이중 중괄호 내 msg는 해당 컴포넌트 인스턴스의 msg 속성 값으로 대체 된다.

- v-once 디렉티브르 사용하여 데이터가 변경되어도 갱신되지 않는 일회성 보간 수행 가능

  한번만 보여지면 될때 (바뀔 필요가 없을때 사용) -메모리 절약가능

 

✅ 이 중 중괄호 내에서는 자바스크립트 표현식 사용이 가능하다.

{{ number + 1 }}

{{ ok ? 'YES' : 'NO' }}

- 하나의 단일 표현식만 포함될 수 있다.

- 함수 호출이 가능하다.

 

ⓑ 원시 html

- 이중 중괄호는 데이터를 HTML이 아닌 일반 텍스트로 해석하기 때문에 실제 HTML을 출력하려면 v-html을 사용

<p>텍스트 보간법 사용: {{ rawHtml }}</p>
<p>v-html 디렉티브 사용: <span v-html="rawHtml"></span></p>

내부 html로 들어가기 때문에 태그 중복 가능성이 있어 div로 선언 해주는 것이 좋음

 <div id="app">
      <div>{{ rawHTML }}</div>
      <div v-html="rawHTML"></div>
    </div>
    <script>
      const App = {
        data() {
          return {
            rawHTML: '<h3 style="color:red;">Raw HTML</h3>',
          };
        },
      };
      const app = Vue.createApp(App);
      const vm = app.mount("#app");

* xxs 공격에 주의해야한다. 

 

 

ⓒ 속성 : v-bind 

<div v-bind:id="dynamicId"></div>
<div :id="dynamicId"></div> // 축약해서 사용가능

// 컴포넌트 형태
  createApp({
    data() {
      return {
        dynamicId: 'red'
      }
    }
  }).mount('#app')

- 해당 요소 (id) 속성을 컴포넌트의 (dynamicId) 속성 - red 와 동기화된 상태로 유지한다

- 위 코드는 <div id="red"></div> 형태가 된다.

 

✅ 불리언 속성

- 참 거짓을 나타낼 수 있다.

<button :disabled="isButtonDisabled">Button</button>

- isButtonDisabled에 true/false 값을 바인딩하여 사용가능하다.

 

 

여러 속성을 동적으로 바인딩

 <div id="app">
      <h1 v-bind:[attr]="'active'">Hello Vue!</h1>
</div>
<script>
      const App = {
        data() {
          return {
            attr: "class",
          };
        },
      };
      const app = Vue.createApp(App);
      const vm = app.mount("#app");
 </script>

위 예시에서는 App 컴포넌트의 attr 속성을 h1의 속성으로 "class" 가 들어가서

실제 돔에서는 <h1 class="active"> 형태가 된다.

주의할 점은 active란 값을 넣기 위해서는 따옴표 안에 작은 따옴표를 넣어줘야 한다.

 

📌 v-bind: 약어 = 콜론기호 ( : 만써도됨) 

* 자주 쓰이기 때문에 위와 같은 형태를 주로 쓴다.

 

 

 

 

 

2. Vue 생명주기

1) 전체 생명 주기

beforeCreate 👉 created 👉 beforeMount 👉 mounted 👉 beforeUnmount 👉 unmounted

① beforeCreate

createApp, mount 메서드로 element에 생성 하고, events와 lifecycle을 초기화 한 후(Init) 실행되는 주기

app = Vue.createApp(options)
app.mount(element);

 

② created

- 데이터의 주입과 반응성 구조를 파악한 후 실행되는 주기

- created 훅이 실행된 후, template 옵션이 있으면 템플릿을 컴파일하고, 없다면 내부 html을 템플릿 형태로 컴파일한다.

 

③  beforeMount

- 준비된 요소들을 html 요소들과 연결 렌더링할 준비 끝

 

④ mounted 

- 연결 후 실행되는 훅

 

⑤ beforeUpdate(전),  updated(후)

- 마운트 이후 실행되는 훅

- 가상돔이 있으면 다른 부분이 있으면(데이터가 바뀌면) 다른 부분만 다시 렌더링 

 

⑥ beforeUnMount, unmount

-  html 요소와 vue 내부 데이터 간 연결(반응성)이 끊어짐

 

 

 

✅ 라이프 사이클 예시

<div id="app">
      <h1>{{ mag }}</h1>
    </div>
    <script>
      const App = {
        data() {
          return {
            mag: "안녕하세요",
          };
        },
        beforeCreate() {
          console.log("beforeCreate !", this.mag);
          console.log(document.querySelector("h1"));
        },
        created() {
          console.log("created !", this.mag);
          console.log(document.querySelector("h1"));
        },
        beforeMount() {
          console.log("beforeMount !", this.mag);
          console.log(document.querySelector("h1"));
        },
        mounted() {
          console.log("mounted !", this.mag);
          console.log(document.querySelector("h1"));
        },
      };
      const app = Vue.createApp(App);
      const vm = app.mount("#app");

create 이전에는(beforeCreate) 내부 데이터와 연결이 안되어 있기때문에 this로 접근 불가능하다. (앱이 생성되지 않음)

mount되었을 때는 돔과 연결된 후이기 때문에 h1이 보이게 된다.

 

 

 beforeUpdate() {
          console.log("beforeUpdate !", this.mag);
          console.log(document.querySelector("h1").textContent);
        },
        updated() {
          console.log("updated !", this.mag);
          console.log(document.querySelector("h1").textContent);
        },

임의로 vue app의 data를 바꿨을 때 beforeUpdate에는 이전 data가 들어갈 것 같지만 그렇지 않다.

update의 의미는, 데이터가 업데이트 되기전 상태가 아니라 화면이 업데이트 되기 전 상태를 의미한다.

전 data를 가져오는 방법은 해당 요소의 textContent를 가져오면 된다.

 

 

beforeUnmount() {
  console.log("beforeUnmount !", this.mag);
  console.log(document.querySelector("h1").textContent);
},
unmounted() {
  console.log("unmounted !", this.mag);
  console.log(document.querySelector("h1").textContent);
},

- unmount되면 연결이 끊겨 화면이 보이지 않지만, 데이터 자체는 접근이 가능하다.

 

 

 

3. Data와 Methods

createApp으로 생성된 앱 인스턴스는 여러 data와 methods가 있다.

 

1) 앱 인스턴스 data 접근

data() {
  return {
    counter: 0,
  };
},

데이터가 위와 같을 때, counter에 접근할 수 있는 방법은 아래와 같다.

vm.count
vm.$data.count

vm['count']
vm.$data['count']

 

2) 프록시

- Vue에서 createApp으로 생성된 인스턴스를 콘솔에 찍어보면 Proxy형태가 나온다.

* 프록시 : 기본적인 동작(속성 접근, 할당, 순회, 열거, 함수 호출 등)의 새로운 행동을 정의할 때 사

 

✅ 사용자 Proxy 생성

const App = {
    data() {
      return {
        count: 0,
      };
    },
};

// Proxy(감시할 타겟 데이터, 핸들러)
const proxyA = new Proxy(App.data, {
    get(target, key) {
      console.log("GETTER!", target, key);
      return target[key];
    },
    set(target, key, value) {
      console.log("SETTER!", target, key, value);
      target[key] = value;
    },
});
const vm = Vue.createApp(App).mount("#app");

- 내부 핸들러에 게터와 세터로 App 데이터에 접근하거나 바꿀 수 있다.

 

 

 

- 프록시를 여러개 생성 했을 때 원본 값에 영향을 주지 않으려면 매개변수에 App.data()형태로 넣어준다.

const proxyA = new Proxy(App.data(), {
	...
});

 

 

 

3) methods

- methods 안에 원하는 커스텀 함수 작성하면 된다.

- 메서드를 정의할때는 화살표 함수를 이용하면 this가 달라짐 따라서 funciton 쓰는걸 권장함

* 디바운싱와 쓰로틀링은 제공하지 않는다.

<style>
      .orange {
        color: orange;
      }
    </style>
    <div id="app">
      <div v-bind:class="{ orange: active}">{{counter}}</div>
      <button v-on:click="increase">click me</button>
    </div>
    <script>
      const App = {
        data() {
          return {
            counter: 0,
            active: true,
          };
        },
        methods: {
          increase() {
            this.counter += 1;
          },
        },
      };

      const app = Vue.createApp(App).mount("#app");
    </script>

 

 

 

 

 

 

728x90