JS 상태를 기반으로 화면에 출력될 HTML을 선언적(declaratively)으로 작성할 수 있습니다.
JS 상태 변경을 추적하고 변경이 발생하면 DOM을 효율적으로 업데이트하는 것을 자동수행 합니다.
즉 데이터가 바뀌면 화면이 바뀐다.
Vue 컴포넌트는 옵션API와 컴포지션API 이렇게 두가지 스타일로 작성할 수 있는데,
우선 옵션API로 구현하는 방법을 알아본다!!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="https://unpkg.com/vue@next"></script> // CDN
</head>
<body>
<div id="app">{{counter}}</div>
<script>
const App = { // Vue의 옵션을 객체로 설정. 객체의 멤버처럼 선언 <<-옵션API
data() {
return {
counter: 0,
};
},
}
const app = Vue.createApp(App).mount("#app"); // Vue.createApp({}).mount(””)
</script>
</body>
</html>
Vue.createApp({ })
vue 어플리케이션을 반환한다.
vue어플리케이션.amount(””)
vue 어플리케이션에 HTML을 연결한 인스턴스를 반환한다.
Vue 옵션 내에서 data()로 데이터를 설정할 수 있다. 초기 반응형 상태를 반환하는 함수로 지정한다.
이때, 일반함수 방식을 사용하고, return 반환값으로 사용할 데이터를 지정해야한다.
+일반함수여야 하는 이유 : 일반함수로 선언한 data() 내부에서 this를 사용하면 생성된 인스턴스에 접근할수 있다.(위 코드에선 app). 하지만 화살표함수로 data()를 선언하면 this가 window를 가리킨다…
+return으로 반환해야하는 이유 : 반환값이 아닌 속성으로 만든 객체가 되면 연결된 다른 어플리케이션에서의 변경에 서로 영향이 생긴다.
데이터 객체내 찾은 모든 속성을 proxy하므로 this.$data.a
뿐만 아니라 this.a
로도 접근 가능
최소 undefined, null 등으로 초기화둔 후에 변경하며 사용하는 것을 권장한다.
Vue 옵션 내에서 methods()로 사용할 메소드를 선언합니다.
methods:{ } 옵션 내에서 메소드형태의 객체로 선언합니다.
메소드 또한 일반함수를 사용합니다.
+일반함수여야 하는 이유 : this를 통해 컴포넌트 인스턴스에 접근할 수 있도록 하기 위해서
...
data() {
return { a: 1 }
},
methods: {
plus() {
this.a++
}
},
created() {
this.plus()
console.log(this.a) // => 2
}
}
v-
디렉티브 속성 값은 단일 JS 표현식이어야 합니다(v-for, v-on, v-slot 제외)
하나 이상의 속성 또는 컴포넌트 prop을 표현식에 동적으로 바인딩
v-bind : 속성 = "값"
<a v-bind:href="url"> ...
<a v-bind:[attributeName]= "url"> ...
:속성=""
<a :href="url"> ...
[ ]
로 감싸서! <a v-bind:[attributeName]= "url"> ...
여기서 `attributeName`은 JavaScript 표현식으로 동적으로 평가되며, 평가된 값은 인자의 최종값으로 사용됩니다. 예를 들어 컴포넌트 인스턴스의 데이터에 `attributeName` 속성값이 `"href"`인 경우, 이 바인딩은 `v-bind:href`와 같습니다.
핸들러에 이벤트 이름도 동적으로 바인딩 할 수 있다!
v-on : 이벤트 = "이벤트핸들러"
<a v-on:[eventName] = "handleSomething" > ...
@이벤트명 =""
<a @[eventName]="handleSomething"> ... <!-- 약어 -->
`eventName`의 값이 `"focus"`인 경우, `v-on:[eventName]`은 `v-on:focus`와 같습니다.
인스턴스 초기화 ⇒ [ beforeCrate ]
⇒ vue 인스턴스 생성 (모든 상태 관리 옵션 처리 완료) ⇒ [ created]
⇒ 템플릿 옵션 확인 후 템플릿 렌더링 ⇒ [ before Mount ]
⇒ 가상 DOM의 내용이 실제 DOM에 부착됨 ⇒ 직후에 [ mounted ]
여기까지 vue옵션지정+HTML구조완 연결 완료, 이후엔 우리가 어떤 상황을 만듦으로써 추가적인 라이프 사이클 동작
data 값 변경 ⇒ [ beforeUpdate ]
⇒ 그리고 나서 변환 값을 가상 DOM에 렌더링! 렌더링 전에 이 값을 이용해 작업은 가능. 그리고 실제 DOM에 변경 반영 ⇒ [ updated ]
연결 끊김 요청 ⇒ [ beforeUnmount ]
⇒ 실제로 끊어짐 ⇒ [ unmounted ]
변경 발생시 beforeUpdate와 updated의 차이를 주의하자
beforeUpdate() {
console.log("beforeUpdate!", this.msg); // 변경 후 값
console.log(document.querySelector("h1").textContent); // 변경전 값
console.log(document.querySelector("h1")); // 변경 후 값
},
updated() {
console.log("updated!", this.msg); // 변경 후 값
console.log(document.querySelector("h1").textContent); // 변경 후 값
},
beforeUpdate는 값이 업데이트되기 전이 아니라 “화면이” 업데이트 되기 전에 발생한다!!
같은 beforeUpdate 상태에서 querySelector("h1").textContent 와 querySelector("h1")에서 출력 결과 다른 이유는
"document.querySelector('h1')으로 검색한 요소는 '요소 참조 객체'라고 해서 요소 정보를 가지고 있는 객체 데이터입니다. 그래서 beforeUpdate() 에서 객체를 콘솔에 출력하는데, 그 객체를 열어 보는 시점은 이미 업데이트된(updated) 상황이기 때문에, 바뀐 값이 출력되는 걸로 보이는 거죠. 그 사이 짧은 순간을 우리가 캐치할 순 없으니 바뀐 값(참조형의 가변성 때문에)만 보게 되는 것이고요. 그래서 .textContent와 같이 바뀌기 전의 값을 문자(원시형의 불변성)로 만들어서 출력하면, 바뀌지 않은 값으로 확인할 수가 있는 거에요." -박영웅강사님
데이터 바인딩의 가장 기본적인 형태는 "Mustache"(이중 중괄호) 문법을 사용한 텍스트 보간법입니다.
<span>메세지: {{ msg }}</span>
v-once
를 사용하여 데이터가 변경되어도 갱시되지 않는 일회성 보간. 메모리 절약 가능!
<span v-once>메세지: {{ msg }}</span>
이중 중괄호는 데이터를 HTML이 아닌 일반 텍스트로 해석합니다.
실제 HTML을 출력하려면 v-html 디렉티브를 사용해야 합니다:
<p>텍스트 보간법 사용: {{ rawHtml }}</p>
<p>v-html 디렉티브 사용: <span v-html="rawHtml"></span></p>
** XSS 주의
이중 중괄호는 HTML 속성(attribute) 내에서 사용할 수 없습니다. 대신 v-bind 디렉티브를 사용하세요:
<div v-bind:id="dynamicId"></div>
데이터 값인 dynamicId 를 id 속성의 값으로써 사용할 수 있다!
boolean 속성의 경우 조금 다르게 작동한다
<button v-bind:disabled="isButtonDisabled">Button</button>
값이 truthy, falsy로 오면 해당하는 값에 따라 속성을 출력하거나 아예 출력하지 않거나 하도록 만듦
데이터 바인딩 내에서 JS표현식의 모든 기능을 지원한다. 단, 단일 표현식에만 가능!! (조건문 등 불가)
{{ number + 1 }}
{{ ok ? '예' : '아니오' }}
{{ message.split('').reverse().join('') }}
<div :id="`list-${id}`"></div>
<!-- 이것은 표현식이 아니라 선언식입니다: -->
{{ var a = 1 }}
<!-- 흐름 제어도 작동하지 않습니다. **삼항 표현식**을 사용하십시오. -->
{{ if (ok) { return message } }}
-- 정리 참고 자료
DAY45 강의 노트
Vue.js 공식문서 guide