
[ Reference ]
https://vuejs.org/guide/essentials/template-syntax.html
Template Syntax | Vue.js
vuejs.org
Vue 는 선언적 바인딩을 가능하게 하는 HTML 기반의 Template 구문을 사용한다. 모든 Vue template 은 HTML Parser 나 규격 호환 브라우저에서 파싱할 수 있는 유효한 HTML이다. Vue 는 template 을 높은 정도로 최적화된 자바스크립트 코드로 컴파일한다.
여기에 반응성 시스템까지 겹쳐서 Vue 는 리렌더링 해야 하는 최소한의 Element 를 파악해 앱 상태가 변경될 때 최소한의 DOM 을 조작할 수 있도록 만든다. (* 의미하는 바를 잘 생각해보자. HTML 을 이용해서 DOM Tree 를 구성한다. 리렌더링은 이 DOM Tree 에 변화를 주는 것이고 리렌더링 하기 위해서는 자바스크립트 언어가 필요하다. 그렇기 때문에 반응성을 위해서 자바스크립트가 HTML을 바라보고 있어야 하는데, Vue 는 이것을 Template 을 통해서 구현하는 것이다.)
만약, Virtual DOM 에 익숙하고 순수 Javascript 의 기능들을 더 선호한다고 하면 Template 기능 대신에 선택적 JSX 지원을 받아 Render Functions 를 사용할 수 있다. 하지만 이 방법이 Vue 내부에서는 Template 과 동일한 정도의 컴파일 최적화를 지니진 못한다. (* 이 점이 Vue 와 React 의 큰 차이점인 것 같다)
1. Text Interpolation
데이터를 바인딩하는 가장 기초가 되는 방식은 Mustache(이중 중괄호) 를 이용해서 문자를 보간하는 방법이다.
<span>Message: {{ msg }}</span>
이중 중괄호는 해 컴포넌트 내에서 msg 속성이 지니는 값으로 대체될 것이다. 그리고 반응성에 다라, msg 값이 바뀌게 되면 그때마다 리렌더링된다.
2. Raw HTML
이 이중 중괄호 방법은 HTML 이 아닌 일반 문자로 해석한다. 만약, HTML 로 반환을 하고 싶다면 ** v-html ** 이라고 하는 directive(디렉티브) 를 사용해야 한다.
<p>Using text interpolation: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
v-html 과 같이 일반적으로 ** v- ** 로 시작하는 것들은 directive(디렉티브) 라고 한다. 디렉티브는 렌더링 된 DOM 에 특별한 반응을 보이도록 하기 위해 사용된다. span 의 내용은 일반적인 HTML 값으로 대체되고 데이터 바인딩은 무시가 된다. Vue 는 문자열 기반의 템플릿 엔진이 아니다. 그렇기 때문에 v-html 을 사용해서 템플릿 부분을 구성할 수 없다. 특히 HTML 을 동적으로 렌더링 하는 행위 자체는 XSS 공격에 취약하다. 그렇기 때문에 웬만하면 자제하고 굳이 사용해야 한다면 신뢰할 수 있는 콘텐츠에서만 사용해야 한다.
3. Attribute Bindings
이중 중괄호는 HTML 속성 안에서 사용할 수 없다. 대신에 ** v-bind ** 라는 디렉티브를 이용해서 데이터를 HTML 속성 값에 바인딩할 수 있다.
<div v-bind:id="dynamicId"></div>
** v-bind ** 디렉티브는 Vue 가 요소의 id 속성을 컴포넌트의 dynamicID 속성과 싱크를 맞추도록 한다. 만약 바인딩한 값이 null 이거나 undefined 가 될 경우, 속성은 리렌더링된 Element에 의해서 제거된다.
** v-bind ** 는 굉장히 자주 쓰이는 디렉티브다 보니 축약형이 나왔다.
<div :id="dynamicId"></div>
** : ** 는 Vue 를 지원하는 브라우저에서 올바르게 파싱이 될 수 있고, 결과물로서 ** : ** 는 나타나지 않는다. 이렇게 축약하는 방식은 다른 디렉티브에서도 많이 사용하고 있기 때문에 나중에 제대로 한 번 공부하는 것이 좋다
** v-bind ( : ) ** 디렉티브를 이용하면 다양한 데이터들을 바인딩할 수 있다. 위에서 처럼 String 을 바인딩할 수도 있고, Boolean 값이나 객체 등도 반환할 수 있다.
4. Using JavaScript Expressions
** v-bind ** 에 국한되지 않고 다양한 디렉티브와 이중 괄호문에서도 데이터를 바인딩할 때, 바인딩될 데이터는 JavaScript 로 표현할 수 있는 것이면 무엇이든 가능하다. 예를 들어 다음과 같은 것들도 바인딩할 수 있다.
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div :id="`list-${id}`"></div>
Expressions Only
단, 오직 Expression 만 가능하다. 코드에서 Expression이란 어떤 값으로 표현될 수 있는 것들을 의미한다. 여기서 우리가 흔하게 아는 자료형들은 다 값으로 표현될 수 있기 때문에 모두 가능하다. 덧붙여서 사칙연산 1+1, 5 *5 도 사칙연산이 된 값을 표현할 수 있기 때문에 가능하다.
하지만 아래와 같이 Statement(프로그래밍에서 실행이 가능한 코드를 의미하며, 변수 할당문과 같은 것들) 나 flow control 들은 바인딩이 될 수 없다(* 다만, 디렉티브에서 몇 가지 예외 사항이 존재한다). 우회적으로 조건식의 경우, if 를 이용해서 값을 바인딩할 수는 없지만 삼항 연산자를 사용하거나 단축 논리 평가법 ( &&, ||, ?? ) 의 경우에는 사용할 수 있다.
{{ var a = 1 }}
{{ if (ok) { return message } }}
Calling Functions
반면, 함수는 가능하다. 함수 그 자체를 바인딩할 수는 없지만 함수를 실행했을 때, 어떤 값이 반환된다면 그 반환된 값은 표현될 수 있는 것이므로 사용이 가능하다. 다만 바인딩할 때 사용되는 함수는 구성 요소가 업데이트될 때마다 호출되는 함수이기 때문에 그 어떤 사이드 이펙트도 발생시키지 않는 순수 함수여야 한다. 즉, 비동기 함수는 사용할 수 없다는 얘기(* 물론, 여기서도 예외가 되는 디렉티브가 있다)
Restricted Global Access
Template 표현 방식은 Sandbox 로 처리가 되므로 제한된 전역 목록에서만 액세스 할 수 있다. 전역 목록은 아래와 같다.
const GLOBALS_WHITE_LISTED =
'Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,' +
'decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,' +
'Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt'
위 목록에 표함되지 않은 전역은 template 표현에서 접근할 수 없다. 단, 위에서 정의되지 않은 글로벌 속성을 정의하고 싶다면 ** app.config.globalProperties ** 에서 명시적으로 정의해줄 수 있다.
5. Diretives
디렉티브는 ** v- ** 접두사가 붙는 특별한 속성이다. ** v-html **, ** v-bind** 를 포함해서 다양한 디렉티브들이 존재한다. 디렉티브 속성 값은 Single JavaScript Expressions 만 받아올 수 있다. (단, v-for, v-on, v-slot 은 제외로 한다) 디렉티브가 하는 일은 디렉티브의 속성 값이 업데이트됐을 때 DOM 에 업데이트를 적용하는 것이다.
Arguments
일부 디렉티브는 디렉티브 이름 뒤에 ** : ** 이 붙고 다음에 오는 것은 Argument, 인자다.
<a v-bind:href="url"> ... </a>
<!-- shorthand -->
<a :href="url"> ... </a>
Dynamic Arguments
디렉티브 인자에 대괄호 ** [ ] ** 를 사용해서 자바스크립트 표현식을 사용할 수 있다. (* 이런 것들을 앞으로 이 블로그 내에서는 동적 인자라고 부르겠다. ...정확한 명칭인지는 모르겠다)
<a v-bind:[attributeName]="url"> ... </a>
<!-- shorthand -->
<a :[attributeName]="url"> ... </a>
attributeName 은 자바스크립트의 표현식을 동적으로 계산을 한다. 그리고 그 계산된 값은 인자의 최종 값으로 바인딩된다. 무슨 말이냐면, 해당 컴포넌트 내에서 attributeName 이라는 것의 값이 href 라고 한다면, ** :[attributeName] ** 과 ** :href ** 는 동일하다는 말이다.
Dynamic Argument Value Constraints
다만, 동적 인자는 String 이나 null 이어야 한다. null 은 바인딩을 없애고자 할 때 사용할 수 있다. (* undefined 가 아님에 주의) 문자열이 아닌 경우에는 에러가 발생한다.
Dynamic Argument Syntax Constraints
첫 번째로 동적 인자로 표현하는데 공백, 따옴표 등과 같은 특정 문자는 HTML 의 속성 이름으로 사용되지 않기 때문에 그런 특정 문자에 대한 제약이 걸려 있다. 밑에 있는 것처럼 사용할 수 없다는 것
<a :['foo' + bar]="value"> ... </a>
다만, 복잡한 동적 인자를 사용할 수 있는 방법으로 ** computed ** 라는 속성을 사용할 수 있다. (* 여기서 복잡하다는 건 'foo' + bar 와 같이 동적으로 계산이 들어가는 것을 의미한다. 그래서 computed 는 계산된 데이터를 저장하기 위해 사용한다고 한다.
두 번째로 in-DOM template 을 사용할 때 브라우저는 속성 이름을 소문자로 강제 전환하기 때문에 대문자로 이름을 지정해서는 안 된다. 예를 들면 밑에서 처럼 카멜 케이스로 작성하면 안 된다는 것
<a :[someAttr]="value"> ... </a>
만약 위의 someAttr 라는 걸 어떻게든 쓰고 싶다면 someattr 로 모두 소문자로 변환해서 사용해야 한다.
Modifiers
Modifier 란 디렉티브 뒤에 ** . ** dot 을 사용해서 표시되는 것으로 앞에서 사용된 디렉티브가 반드시 특별한 방식으로 바운딩돼야 한다는 것이다. 예를 들어서 ** .prevent ** 라는 수식어는 v-on 디렉티브에서 event.preventDefault( ) 를 실행시키는 것과 동일하다.
<form @submit.prevent="onSubmit">...</form>
'(준)공식 문서 > Vue.js' 카테고리의 다른 글
[ Vue.js 3 공식 문서 ] 2. Essentials - Computed Properties ( computed ) (0) | 2022.02.18 |
---|---|
[ Vue.js 3 공식 문서 ] 2. Essentials - Reactivity Fundamentals ( 반응성 기본 원칙 ) (0) | 2022.02.18 |
[ Vue.js 3 공식 문서 ] 2. Essentials - Creating an Application (0) | 2022.02.18 |
[ Vue.js 3 공식 문서 ] 1. Getting Started (0) | 2022.02.17 |
[ Vue.js 3 공식 문서 ] 시작합니다 (0) | 2022.02.17 |