Vue.js는 HTML 기반의 템플릿 문법을 제공한다.
이는 선언적으로 DOM에 Vue instance data를 바인딩할 수 있게 해준다.
모든 Vue.js 템플릿은 스펙을 호환하는 브라우저와 HTML 파서로 구문을 분석할 수 있는 유효한 HTML이다.
💡 내부적으로 Vue는 템플릿을 가상 DOM 렌더링 함수로 컴파일한다.
반응형 시스템과 결합하여, 뷰는 앱의 상태가 변화할 때 리렌더링해야할 최소한의 컴포넌트를 찾아서, 최소한의 DOM 조작을 하게 된다.
그냥 JS로 하고 싶으면, 템플릿 대신에 렌더링함수를 직접 작성할 수 있다. 선택사항으로 JSX를 지원한다.
{{ }}
가장 기본적인 데이터 바인딩의 형태는 "Mustache" 신택스를 사용한 텍스트 보간법이다.
"Mustache" 신택스는 중괄호를 사용한다.
<span>{{msg}}</span>
mustache 태그는 데이터 객체의 msg 프로퍼티의 값으로 대체될 것이다.
또한, msg 값이 변화할 때마다 업데이트된다.
v-once
디렉티브를 사용하면, 데이터가 변화하여도 업데이트가 안되게 할 수 있다.
그러나, 이는 같은 노드에 있는 다른 바인딩에도 영향을 준다는 것을 유의해야 한다.
❓ 이거 무슨말인지 모르겠다!
<span v-once>절대 변하지 않는 값 -> {{msg}} 왜냐면 v-once 디렉티브를 썼기 때문에!</span>
v-html
double mustaches는 데이터를 플레인 텍스트로 해석한다.
만약, HTML로 해석해야 한다면, v-html
디렉티브를 사용해야 한다.
const vm = new Vue({
el: '#app1',
data: {
rawHtml: `<span style="color:red">빨간색 글씨가 나와야 한다.</span>`,
},
});
<div id="app1">
<p>mustaches : {{ rawHtml }}</p>
<p>v-html : <span v-html="rawHtml"></span></p>
</div>
span
의 컨텐츠는 rawHtml
프로퍼티의 값으로 대체되며, 플레인 HTML로 해석된다. 이 때, 데이타 바인딩은 무시된다. (❓ 모르겠음.)
v-html
을 템플릿을 사용하는데 사용해서는 안된다. 뷰는 스트링 기반의 템플릿 엔진이 아니기 때문이다. 그 대신에, 컴포넌트를 사용할 것을 권한다. 컴포넌트는 UI 재사용과 구성의 기본 단위로 쓰이게 된다.
⚠️ 동적으로 임의의 HTML이 렌더링 되는 것은 매우 위험하다. 이는 XSS 취약점으로 쉽게 이어질 수 있기 때문이다. HTML 보간법은 신뢰할 수 있는 컨텐츠에만 사용하고, 절대 사용자가 제공하는 컨텐츠에는 사용하지 않아야 한다.
❓ XSS 취약점?
v-bind
mustaches는 html 속성 안에 사용될 수 없다.
대신, v-bind
디렉티브를 사용하면 된다.
<div v-bind:id='dynamicId'></div>
boolean 속성을 사용할 때, 조금 다르게 동작한다.
여기서 isButtonDisabled
가 null, undefined, false일 경우에는
disabled
속성이 <button>
엘리먼트에 포함되지도 않는다.
isButtonDisabled가 true일 경우
disabled 속성이 포함되었음을 확인할 수 있다.
isButtonDisabled가 undefined인 경우
disabled 속성이 포함되지 않은 것을 확인할 수 있다.
Vue는 데이터 바인딩 안에 JS expression을 완전히 지원한다.
const app3 = new Vue({
el: '#app3',
data: {
number: 100,
ok: false,
message: '안녕하세요',
id: 10,
},
});
<div id="app3">
<div v-bind:id="'list-' + id">check out id</div>
number : {{ number + 1}}
{{ok ? 'yes' : 'no'}}
{{message.split('').reverse().join('')}}
</div>
단, 각 바인딩마다 하나의 expression만 포함되어야 한다.
다음은 동작하지 않는 경우이다.
<!-- 이는 expression이 아닌 statement이다. -->
{{ var a = 1 }}
<!-- flow control도 동작하지 않는다. 삼항연산자를 사용해야 한다.-->
{{ if(ok) {return message} }}
⚠️ 템플릿 expression은 샌드박스되어있고, Math
, Date
와 같은 whitelist of globals에만 접근할 수 있다. 템플릿 expression 안에서 사용자 정의 전역 변수에 접근하면 안된다.
const allowedGlobals = makeMap(
'Infinity,undefined,NaN,isFinite,isNaN,' +
'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +
'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' +
'require' // for Webpack/Browserify
)
디렉티브는 v-
를 접두사로 갖는 속성이다.
디렉티브 속성의 값은 하나의 JS Expression이어야 한다. (v-for
은 예외)
디렉티브의 역할은 expression의 값이 변경되었을 때, reactively 사이드 이펙트를 DOM에 적용시키는 것이다.
<p v-if="seen">Now you see me</p>
v-if
는 seen
의 값이 true인지 false인지에 따라서 , <p>
엘리먼트를 DOM에 추가하거나 삭제할 것이다.
어떠한 directive는 argument를 가질 수 있다. 이 argument는 디렉티브 이름 옆에 콜론으로 표시된다.
예를 들어, href
는 argument인데, 이는 v-bind 디렉티브에게 href 속성의 값을 url로 바인드해야함을 말해준다.
<div id="app4">
<a v-bind:href="url">kakao for business</a>
</div>
const app4 = new Vue({
el: '#app4',
data: {
url: 'https://business.kakao.com/',
},
});
v-on
디렉티브는 DOM 이벤트를 리스닝하고 있다.
여기서 argument는 리스팅하고 있는 이벤트이다.
<div id="app5">
<button v-on:click='alertHi'>click me!</button>
</div>
const app5 = new Vue({
el: '#app5',
data: {
alertHi() {
alert('hi');
},
},
});
2.6.0 버전부터, 대괄호(square bracket)에 감싼 JS expression을 디렉티브의 argument로 사용하는 것이 가능해졌다.
<!--
Note that there are some constraints to the argument expression, as explained
in the "Dynamic Argument Expression Constraints" section below.
-->
<a v-bind:[attributeName]="url"> ... </a>
<a v-on:[eventName]="doSomething"> ... </a>
attributeName
과 eventName
은 vue instance에 있을 data 프로퍼티의 값으로 대체된다.
-> 사용방식을 더 살펴봐야 할 것 같ㄷ.
수식어는 디렉티브를 특별한 방식으로 바인딩해야 함을 나타낸다.
예를들어 .prevent
가 붙으면, 그 이벤트는 event.preventDefault()
를 호출하도록 v-on 디렉티브에게 알려주어야 한다.
가장 자주 사용되는 v-bind
와 v-on
에 약어가 있다.
v-bind
약어 : v-bind를 삭제
<!-- 전체 문법 -->
<a v-bind:href="url"> ... </a>
<!-- 약어 -->
<a :href="url"> ... </a>
<!-- shorthand with dynamic argument (2.6.0+) -->
<a :[key]="url"> ... </a>
v-on
약어 : @eventName
<!-- 전체 문법 -->
<a v-on:click="doSomething"> ... </a>
<!-- 약어 -->
<a @click="doSomething"> ... </a>
<!-- shorthand with dynamic argument (2.6.0+) -->
<a @[event]="doSomething"> ... </a>
or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Syncing