데브코스

[Day 33] 반응성, 디렉티브, 라이프 사이클, data & methods

라다디 2022. 12. 2. 21:43

VueJS

Vue.js사용자 인터페이스를 만들기 위한 자바스크립트 프레임워크다. 

 

소개 | Vue.js

 

v3-docs.vuejs-korea.org

CDN을 사용하여 HTML의 상단에 script를 불러와서 간단하게 사용할 수 있다.

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

 

Vue 시작하기

반응성

<body>
  <div id="app">{{ counter }}</div>
  <script>
    Vue.createApp({
      data() {
        return {
          counter: 0,
        };
      },
      mounted() {
        setInterval(() => {
          this.counter += 1;
        }, 1000);
      },
    }).mount("#app");
  </script>
</body>

예제의 결과를 브라우저에서 확인하면 1초마다 1이 증가하는 것을 확인할 수 있다. 

현재 couter라는 데이터와 DOM이 연결된 상태이고 이렇게 데이터가 변경이 되면 연결되어 있는 화면도 같이 변경되는 것을 반응성이라고 한다. 

 

디렉티브

<body>
  <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>
</body>

v-로 시작하는 속성들을 디렉티브라고 부른다.

디렉티브는 VueJS의 문법으로 렌더링 된 DOM에 반응형 동작을 하도록 도와준다.

 

  • v-bind 디렉티브를 사용하여 html의 속성에 view model의 데이터를 연결할 수 있다. 약어는 :이다.
  • v-on 디렉티브를 사용하여 이벤트 핸들러를 추가할 수 있다. 약어는 @이다.
  • v-if 디렉티브를 사용하여 조건에 따라 렌더링 여부를 결정한다. 
  • v-for 디렉티브를 사용하여 이터러블 데이터를 순회할 수 있다. 
  • v-once 디렉티브를 사용하여 데이터가 변경되어도 갱신하지 않는 일회성 보간을 작성할 수 있다.
  • v-html 디렉티브를 사용하여 이중 중괄호 구문 안에 html을 출력할 수 있다. (XSS 취약 주의)

 

디렉티브의 속성 이름은 동적으로 작성할 수 있다. 

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

 

예제

<body>
  <div id="app">
    <div v-if="active">Hello Vue!</div>
    <button v-on:click="toggle">Toggle</button>
  </div>
  <script>
    const App = {
      data() {
        return {
          active: false,
        };
      },
      methods: {
        toggle() {
          this.active = !this.active;
        },
      },
    };
    const app = Vue.createApp(App).mount("#app");
  </script>
 </body>

원리

Hello Vue!라는 텍스트를 가지고 있는 div에 v-if라는 디렉티브를 추가해서 active라는 데이터를 연결한다.

그리고 이 데이터를 toggle이라는 메소드를 통해 반대되는 값으로 변경한다.

true 혹은 false 값을 지니게 되는데 그 값을 v-if가 판단해서 true라면 화면에 출력하고 false라는 출력하지 않는다.

 

컴포넌트 

<script>
  const FruitItem = {
    template: "<li>{{ fruitName }}</li>",
    props: ["fruitName"],
  };

  const App = {
    components: {
      FruitItem,
    },
    data() {
      return ;
    },
  };
  const app = Vue.createApp(App).mount("#app");
</script>

FruitItem이라는 객체를 만들고 template과 props 속성을 작성한다.

props로 받을 데이터의 이름을 정해주고 template에 전달을 해주는 개념이다.

component 이름파스칼 케이스, props 이름카멜 케이스로 작성한다.

 

App에는 components 객체를 만들고 생성한 컴포넌트를 작성한다.

<div id="app">
  <ul>
    <fruit-item fruit-name="Orange"></fruit-item>
  </ul>
</div>

components에 정의한 컴포넌트를 HTML에서 사용하려면 컴포넌트 이름의 태그를 만들고 props에 전달할 데이터를 작성한다. 

태그명과 전달해줄 데이터 케밥 케이스로 작성한다.

 

라이프 사이클

Vue 컴포넌트 인스턴스는 생성될 때 일련의 초기화 단계를 거친다.

이 과정에서 라이프 사이클 훅 함수를 사용할 수 있다. 

 

수명 주기 훅 | Vue.js

 

v3-docs.vuejs-korea.org

beforeCreate() {
  // VueJS 어플리케이션이 생성되기 전
},
created() {
  // VueJS 어플리케이션이 생성된 직후
},
beforeMount() {
  // DOM element 연결되기 직전
},
mounted() {
  // DOM element 연결된 직후
},
beforeUpdate() {
  // 데이터 변경 후 화면이 업데이트 되기 전 (데이터가 업데이트 되기 전이 아님)
},
updated() {
  // 데이터와 화면 모두 변경사항이 반영된 직후
},
beforeUnmount() {
  // DOM element와 연결이 끊기기 직전
},
unmounted() {
  // DOM element와 연결이 끊어진 후
},

 

템플릿 문법

이중 중괄호 구문 {{ }}을 사용하여 문자열 보간 기능을 사용할 수 있다. 

<p>메세지: {{ message }}</p>

위 코드의 이중 중괄호 구문은 컴포넌트 인스턴스의 message 속성 값으로 대체되며, 속성 값이 변경될때마다 갱신된다.

<h1 v-bind:class="name">{{ name + '입니다' }}</h1>
<h1>{{ count + 100 }}</h1>

이중 중괄호 구문 내에서는 단일 표현식을 지원한다.

 

Data & Methods

Data

VueJS는 반응형 데이터에 접근할 때 $data라는 내장 객체에 접근해서 확인할 수 있다. 

const app = Vue.createApp({
  data() {
    return { count: 4 }
  }
})

const vm = app.mount('#app')

console.log(vm.$data.count) // => 4
console.log(vm.count)       // => 4

vm.count = 5
console.log(vm.$data.count) // => 5

vm.$data.count = 6
console.log(vm.count) // => 6

인스턴스 속성은 인스턴스가 처음 생성될 때만 추가되므로 원하는 값을 사용할 수 없는 속성에는 null, undefined 같은 값을 주어 초기화하는 것이 좋다. 

새로운 속성을 data에 포함하지 않고 컴포넌트 인스턴스에 직접 추가할 수 있지만 이렇게 추가한 속성은 반응형 $data 객체로 처리되지 않기 때문에 Vue의 반응형 시스템에 의해 자동으로 추적되지 않는다. 

 

Proxy

Proxy는 특정 데이터가 언제 조회되고 언제 값이 할당되는지 감시한다.

따라서 proxy를 통해 화면에 출력되는 로직을 담당할 수 있다.

const app = {
  data: {
    count: 0,
  },
};

// Proxy(target, handler)
// target: 감시할 데이터
// handler: 데이터를 가져와서 조작한 후 반환 가능
const proxyA = new Proxy(app.data, {
  get(target, key) {
    console.log("Getter");
    return target[key];
  },
  set(target, key, value) {
    console.log("setter");
    target[key] = value * 2;
  },
});

const proxyB = new Proxy(app.data, {
  get(target, key) {
    console.log("Getter");
    return target[key];
  },
  set(target, key, value) {
    console.log("setter");
    target[key] = value * 2;
  },
});

위 코드에서 data가 객체(= 참조형 데이터)이므로 proxyA에서 count의 값이 바뀌면 proxyB에도 영향이 미친다. 

그렇기 때문에 data 옵션은 함수를 반환해야 한다. 

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

 

Methods

컴포넌트 인스턴스에 함수를 추가하기 위해 methods를 사용할 수 있다.

const App = {
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    increase() {
      this.count += 1; // this는 vm
    },
  },
};

method를 선언할 때 화살표 함수를 사용하면 Vue가 적절한 this 값을 바인딩하지 못한다.

따라서 함수를 정의할 때화살표 함수를 사용하지 말아야 한다

함수 내부에서 사용하는 것은 상관없다.

  • 일반 함수의 this는 함수가 실행될 때 정의된다.
  • 화살표 함수의 this는 함수가 만들어질 때 정의된다.

 


출처: 프로그래머스 프론트엔드 데브코스 

[Day 33] Vue (1)