Luna Tech

Tutorials For Dummies.

Vue: Template Syntax

2022-03-15


0. Intro

Reference

Vue 是基于 HTML template syntax,我们可以声明式地去绑定 DOM 和 underlying component instance’s data.

Vue 会把 template 编译成 highly-optimized JS code,当 app state 变化时,智能化地 re-render 最少数量的 component 以及使用最少的 DOM manipulation。

如果你熟悉 Virtual DOM 的概念,想要用原生 JS 的话,你可以直接写 render function,不需要用 template,但是这样就享受不到 compile-time optimization 了。


1. 插入文字 Text Interpolation

<span>Message: {{ msg }}</span>

通过"Mustache" syntax (double curly braces) 来进行 data binding。

双大括号里面的 msg 会被 component instance 的 msg property 所替换,而且当 msg property 发生变化时也会实时变化。


2. Raw HTML

上面的双大括号只能把 data 转换为 plain text,而不是 HTML,想要输出 raw HTML,就要用 v-html directive:

<p>Using text interpolation: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>

假设我们有 rawHtml property,用 v-html 可以把这个 element 的 innerHTML 与这个 property 绑定。

注意:Raw HTML render 会忽略 data binding,因为 Vue 不是一个 string-based templating engine,所以你不能用 v-html 来组成 template partials。

Component 才是 Vue 的 fundamental unit,假如要 break down,就应该 break down 成多个 component。

安全隐患 - XSS

v-html 只能用在信任的内容上,不能让用户来控制 input。

Dynamically rendering arbitrary HTML on your website can be very dangerous because it can easily lead to XSS vulnerabilities . Only use v-html on trusted content and never on user-provided content.


3. HTML Attribute Bindings

我们用 v-bind directive 来管理 html attributes,假如下面示例的 dynamicId property 是 null 或者 undefined,那么这个 attribute 就会从 rendered element 中移除。

<div v-bind:id="dynamicId"></div>

v-bind 的简化写法

<div :id="dynamicId"></div>

Boolean Attributes

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

假如 isButtonDisabled 是一个 truthy value,那么 disabled attribute 就会被包含进去。

假如 isButtonDisabled""(一个 falsy value),它也会被包含进去。

<button disabled="">

Multiple Attributes

我们可以用一个 object 来表示相关的 attributes,比如:

data() {
  return {
    objectOfAttrs: {
      id: 'container',
      class: 'wrapper'
    }
  }
}

在绑定的时候,我们不需要提供 argument(v-bind:attr1),直接用 v-bind 就行了。

<div v-bind="objectOfAttrs"></div>

4. Use JS Expressions

在 vue template 中哪些地方可以用 JS expression?

  1. 在双大括号里面;
  2. 在任何 Vue directive 的 attribute value 里面;

这些 expression 会在 current component instance 的 data scope 里面用 JS 来 evaluate。

Examples

{{ number + 1 }}

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

{{ message.split('').reverse().join('') }}

<div :id="`list-${id}`"></div>

不 working 的 examples

每个 binding 只能有 one single expression,所以以下是反面例子。

<!-- this is a statement, not an expression: -->
{{ var a = 1 }}

<!-- flow control won't work either, use ternary expressions -->
{{ if (ok) { return message } }}

Call functions

我们还可以在 binding expression 里面调用 component-exposed method,如下面的 formatDate 和 toTitleDate:

<span :title="toTitleDate(date)">
  {{ formatDate(date) }}
</span>

Functions called inside binding expressions will be called every time the component updates, so they should not have any side effects, such as changing data or triggering asynchronous operations.

注意:这种在 binding expression 里面的 function 会在 component 每次 update 的时候都调用,所以不要调用一些涉及 data changing 或者 async 相关的 function。

有限的全局权限 Restricted Globals Access

Template expressions 只能 access 部分 globals,像 window 这种跟用户相关的 property 也不能 access,除非你 change config。

这是为了保证 template expression 的安全性和轻量型。

core/globalsWhitelist.ts at main · vuejs/core · GitHub

Globals not explicitly included in the list, for example user-attached properties on window, will not be accessible in template expressions. You can, however, explicitly define additional globals for all Vue expressions by adding them to app.config.globalProperties .


5. Directives - special attributes

Example: v-if

当 seen = truthy 的时候,我们可以看到这个 p element。

<p v-if="seen">Now you see me</p>

Arguments

一些 directive 可以有 arguments,通过 :xxx 的格式来传入,比如 href 就是一个 argument,告诉 Vue 我们想要 bind href 这个 html attribute 和我们后面 pass in 的 "url" property。

<a v-bind:href="url"> ... </a>

<!-- shorthand -->
<a :href="url"> ... </a>

v-on directive 会监听 DOM 事件,shorthand 是 @event

<a v-on:click="doSomething"> ... </a>

<!-- shorthand -->
<a @click="doSomething"> ... </a>

Dynamic Arguments

假如我们不确定要用哪个 argument 呢?可以在 [] 里面使用 JS expression。

<!--
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>

<!-- shorthand -->
<a :[attributeName]="url"> ... </a>

<a v-on:[eventName]="doSomething"> ... </a>

<!-- shorthand -->
<a @[eventName]="doSomething">

这个例子里面的 attributeName 会被动态 evaluate 成一个 JS expression,它的 evaluated value 会成为这个 argument 的最终值。比如 attributeName = href,那么上面的 code 就等于 v-bind:href

Dynamic Argument Value Constraints

evaluated value 必须是一个 string 或者 null value。

null 可以用于 explicitly remove the binding。

其他非 string value 都会触发警告。

Dynamic Argument Syntax Constraints

一些符号不能用,比如括号,引号之类的,如下:

<!-- This will trigger a compiler warning. -->
<a :['foo' + bar]="value"> ... </a>

解决方法:computed property

Convention

不要在 in-DOM template(templates directly written in an HTML file) 里面用大写字母,因为浏览器会自动把这些名字转成小写。

<a :[someAttr]="value"> ... </a>

Modifiers

Modifiers are special postfixes denoted by a dot, which indicate that a directive should be bound in some special way.

Note: submit 后面的那个 prevent 就是 modifier,告诉 v-on directive 在触发事件上调用 event.preventDefault()

<form @submit.prevent="onSubmit">...</form>

Directive syntax