• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 模板语法

    Vue 使用一种基于HTML的模板语法,使我们能够声明式地将其组件实例的数据绑定到呈现的 DOM 上。所有的 Vue 模板都是语法层面合法的HTML,可以被符合规范的浏览器和HTML解析器解析。

    在底层机制中,Vue 会将模板编译成高度优化的 JavaScript 代码。结合响应式系统,当应用状态变更时,Vue 能够智能地推导出需要重新渲染的组件的最少数量,并应用最少的 DOM 操作。

    如果你对虚拟 DOM的概念比较熟悉,并且偏好直接使用 JavaScript,你也可以结合可选的 JSX 支持,直接手写渲染函数而不采用模板。但请注意,这将不会享受到和模板同等级别的编译时优化。


    数据绑定

    文本

    最基本的数据绑定形式是文本插值,它使用的是“Mustache”语法(即双大括号):

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

    双大括号标签会被替换为相应组件实例中msg property 的值。同时每次msg property 更改时它也会同步更新。

    通过使用v-once指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定:

    <span v-once>这个将不会改变: {{ msg }}</span>
    


    原始 HTML

    双大括号将会将数据插值为纯文本,而不是 HTML。若想插入 HTML,你需要使用v-html指令:

    //HTML
    <div id="example1" class="demo">
        <p>Using mustaches: {{ rawHtml }}</p>
        <p>Using v-html directive: <span v-html="rawHtml"></span></p>
    </div>
    
    //JS
    const RenderHtmlApp = {
      data() {
        return {
          rawHtml: '<span style="color: red">This should be red.</span>'
        }
      }
    }
    
    Vue.createApp(RenderHtmlApp).mount('#example1')
    

    HTML 渲染结构

    这里我们遇到了一个新的概念。这里看到的v-html attribute 被称为一个指令。指令由v-作为前缀,表明它们是一些由 Vue 提供的特殊 attribuite,你可能已经猜到了,它们将为渲染的 DOM 应用特殊的响应式行为。这里我们做的事情简单来说就是:在当前组件实例上,将此span元素的innerHTMLrawHtml property 保持同步。

    span的内容将会被替换为rawHtml property 的值,插值为纯 HTML——数据绑定将会被忽略。注意,你不能使用v-html来拼接组合模板,因为 Vue 不是一个基于字符串的模板引擎。相反,组件应该作为 UI 重用和组合的基本单元。


    安全警告:
    在网站上动态渲染任意 HTML 是非常危险的,因为这非常容易造成XSS漏洞。请仅在内容安全可信时再使用v-html,并且永远不要使用用户提供的 HTML 内容。


    Attribute 绑定

    双大括号不能在 HTML attributes 中使用。相应的,应该使用v-bind指令:

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

    v-bind指令指示 Vue 将元素的id attribute 与组件的dynamicId property 保持一致。如果绑定的值是null或者undefined,那么该 attribute 将会从渲染的元素上移除。


    缩写

    因为v-bind特别常用,有相应的缩写语法:

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

    开头为:的 attribute 可能和一般的 HTML attribute 看起来不太一样,但它的确是合法的 attribute 名称字符,并且所有支持 Vue 的浏览器都能正确解析它。此外,他们不会出现在最终渲染的标签中。缩写语法是可选的,但相信在你了解了它更多的用处后,你应该会更喜欢它。


    布尔型 Attribute

    布尔型 attribute 依据true/false值,决定 attribute 是否应该存在于该元素上。disabled就是最常见的例子之一。

    v-bind在这种场景下的行为不太一样:

    <button v-bind:disabled="isButtonDisabled">按钮</button>
    
    • 如果isButtonDisabled的值,为truthy(真值)或一个空字符串(即<button disabled="">)时,渲染出来的<button>元素中,会包含disabled attribute,使<button>按钮处于禁用状态。
    • 如果isButtonDisabled的值,为falsy(假值),attribute 将被忽略。此例中,渲染出来的<button>元素中,不包含disabled attribute,使<button>按钮处于可用状态。
    • falsy(假值)是在 Boolean 上下文中认定为 false 的值。在 JavaScript 中只有 8 个 falsy 值。
      • false
      • ""(空字符串)
      • 0(数字:零)
      • -0(数字:负零)
      • 10n(一个整数字面量后面加 n 的方式定义一个 BigInt,如:10n)
      • null
      • undefined
      • NaN
    • Truthy(真值)指的是在布尔值上下文中,转换后的值为 true 的值。被定义为falsy(假值)以外的任何值都为真值。


    动态绑定多个值

    如果你有像这样的一个包含多个 attribute 的 JavaScript 对象:

    const objectOfAttrs = {
        id: 'container',
        class: 'wrapper'
    }
    

    通过不带参数的v-bind,你可以将它们绑定到单个元素上:

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


    使用 JavaScript 表达式

    至此,我们仅在模板中绑定了一些简单的 property 键。但是 Vue 实际上在所有的数据绑定中都支持完整的 JavaScript 表达式:

    {{ number + 1 }}
    
    {{ ok ? 'YES' : 'NO' }}
    
    {{ message.split('').reverse().join('') }}
    
    <div :id="`list-${id}`"></div>
    

    这些表达式都会被作为 JavaScript ,以组件为作用域,解析执行。

    在 Vue 模板内,JavaScript 表达式可以被使用在如下场景上:

    • 在文本插值中(双大括号)。
    • 在任何 Vue 指令attribute(以v-开头的特殊 attribute)的值中。


    仅支持表达式

    每个绑定仅支持单一表达式,也就是一段能够被求值的 JavaScript 代码。一个简单的判断方法是,是否可以合法地写在return后面。因此,所以下面的例子都是无效的。

    <!-- 这是一个语句,而非表达式 -->
    {{ var a = 1 }}
    
    <!-- 条件控制同样不会工作,请使用三元表达式 -->
    {{ if (ok) { return message } }}
    


    调用函数

    在绑定的表达式中,可以使用一个组件暴露的方法。

    <span :title="toTitleDate(date)">
      {{ formatDate(date) }}
    </span>
    
    绑定在表达式中的方法,在组件每次更新时,都会被重新调用,因此不应该产生任何effect(副作用)。比如改变数据或触发异步操作。


    受限的全局访问

    模板中的表达式将被沙盒化,仅能够访问到有限的全局对象列表。该列表中,会暴露常用的内置全局对象,比如MathDate

    没有显式包含在列表中的全局对象,将不能在模板内表达式中访问。例如,用户附加在window上的 property。然而,你也可以自行在app.config.globalProperties上显式地添加他们,供所有的 Vue 表达式使用。

    // globalsWhitelist.ts 
    import { makeMap } from './makeMap'
    
    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'
    
    export const isGloballyWhitelisted = /*#__PURE__*/ makeMap(GLOBALS_WHITE_LISTED)
    


    指令

    指令是带有v-前缀的特殊 attribute。Vue 提供了许多内置指令,包括上面我们所介绍的v-bindv-html

    指令 attribute 的期望值,为一个 JavaScript 表达式(之后要讨论到的v-forv-onv-slot将会是例外)。使用指令是为了,在其表达式值变化时,响应式的更新 DOM。以v-if为例:

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

    这里,v-if指令是基于表达式seen的值的truthy(真值)或falsy(假值)来插入或移除<p>元素。


    参数

    一些指令能够接收一个“参数”,在指令名称之后以:(冒号)隔开,做标识。例如,v-bind指令可以用于响应式地更新 HTML attribute:

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

    这里href就是一个参数,它告诉v-bind指令,将表达式url的值,绑定到元素的href attribute 上。在缩写中,参数前的一切(例如v-bind:)都会被缩略为一个:字符。


    另一个例子是v-on指令,它用于监听 DOM 事件:

    <a v-on:click="doSomething"> ... </a>
    
    <!-- 缩写 -->
    <a @click="doSomething"> ... </a>
    

    这里的参数是要监听的事件名称:clickv-on也是少部分含有缩写的指令之一,缩写字符为@


    动态参数

    同样在指令参数上也可以使用一个 JavaScript 表达式,需要包含在一对[](方括号)内:

    <!--注意,参数表达式有一些约束,参见下面“动态参数表达式约束”一节的解释。-->
    <a v-bind:[attributeName]="url"> ... </a>
    
    <!-- 缩写 -->
    <a :[attributeName]="url"> ... </a>
    

    这里的attributeName会被作为一个 JavaScript 表达式进行动态求值,求得的值将会作为最终的参数来使用。例如,如果你的组件实例有一个data property attributeName,其值为"href",那么这个绑定将等价于v-bind:href

    同样地,你可以使用动态参数为一个动态的事件名绑定处理函数:

    <a v-on:[eventName]="doSomething"> ... </a>
    
    <!-- 缩写 -->
    <a @[eventName]="doSomething">
    

    在这个示例中,当eventName的值为"focus"时,v-on:[eventName]将等价于v-on:focus


    动态参数值的限制

    动态参数期望结果为一个字符串,或者是null。特殊值null意为,显式移除该绑定。其他任何非字符串的值,都将触发一个警告。


    动态参数语法的限制

    动态参数表达式因为某些字符的缘故有一些语法限制,比如空格和引号,在 HTML attribute 名称中都是不合法的。例如下面的示例:

    <!-- 这会触发一个编译器警告 -->
    <a :['foo' + bar]="value"> ... </a>
    

    如果你需要传入一个复杂的动态参数,我们推荐使用计算属性替换复杂的表达式,也是 Vue 最基础的概念之一,我们很快就会讲到。

    当使用DOM 内嵌模板(直接写在 HTML 文件里的模板)时,我们需要避免在名称中使用大写字母,因为浏览器会强制将其转换为小写

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

    上面的例子将会在 DOM 内嵌模板中被转换为:[someattr]。如果你的组件拥有“someAttr” property 而非“someattr”,这段代码将不会工作。


    修饰符

    修饰符(modifier)是以.(半角句号)开头的特殊后缀,表明指令需要以一些特殊的方式被绑定。例如,.prevent修饰符告诉v-on指令,对于触发的事件,调用event.preventDefault()

    <form v-on:submit.prevent="onSubmit">...</form>
    
    <!-- 缩写 -->
    <form @:submit.prevent="onSubmit">...</form>
    

    之后在讲到v-onv-model的功能时,你将会看到其他修饰符的例子。

    最后,在这里你可以直观地看到完整的指令语法:

    上篇:vue 应用实例

    下篇:响应式基础