跳至主要內容

Vue

LincZero大约 9 分钟

Vue

目录

模板语法

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

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

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

文本插值(“Mustache”语法)

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

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

原始 HTML(v-html)

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

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

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

[|安全警告]

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

Attribute 绑定

双大括号不能在 HTML attributes 中使用。想要响应式地绑定一个 attribute,应该使用 v-bind 指令open in new window

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

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

因为 v-bind 非常常用,我们提供了特定的简写语法:

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

布尔型 Attribute

[|笔者]:(这个好像是新增的)

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

v-bind 在这种场景下的行为略有不同:

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

isButtonDisabled真值open in new window或一个空字符串 (即 <button disabled="">) 时,元素会包含这个 disabled attribute。 而当其为其他假值open in new window时 attribute 将被忽略

动态绑定多个值

<div v-bind="objectOfAttrs"></div>
const objectOfAttrs = {
  id: 'container',
  class: 'wrapper'
}

使用 JavaScript 表达式

Vue 实际上在所有的数据绑定中都支持完整的 JavaScript 表达式

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

JavaScript 表达式可以被使用在如下场景上:

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

仅支持表达式

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

因此,下面的例子都是无效的:

<!-- 这是一个语句,而非表达式 -->
{{ var a = 1 }}

<!-- 条件控制也不支持,请使用三元表达式 -->
{{ if (ok) { return message } }}

调用函数

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

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

[|TIP] 绑定在表达式中的方法在组件每次更新时都会被重新调用,因此应该产生任何副作用,比如改变数据或触发异步操作。

受限的全局访问

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

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

指令 Directives

指令是带有 v- 前缀的特殊 attribute

参数 Arguments

动态参数

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

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

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

这里的 attributeName 会作为一个 JavaScript 表达式被动态执行,计算得到的值会被用作最终的参数。 举例来说,如果你的组件实例有一个数据属性 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>

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

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

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

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

修饰符 Modifiers

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

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

之后在讲到 v-onopen in new windowv-modelopen in new window 的功能时,你将会看到其他修饰符的例子。

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

总结

新总结

  • 数据单向绑定

    • Mustache 语法

      <h1>{{ message }}</h1>
      
    • v-html

      <h1 v-html='message'></h1>
      
    • v-text

      <h1 v-text='message'></h1>
      
  • 数据双向绑定

    • v-model

      <input type="text" v-model="message"/>
      
  • 属性单向绑定

    • v-bind

      <h1 v-bind:id="dynamicId"></h1>
      <!-- 简写 -->
      <h1 :id="dynamicId"></h1>
      
  • 函数绑定

    • v-on

      <button v-on:click="handleIncrement"></button>
      <!-- 简写 -->
      <button @click="handleIncrement"></button>
      

旧笔记的总结

<div id="app">
	<!-- 4种数据绑定----------------------------------------->
    <h1>{{ message }}</h1>								// 数据绑定  {{}}、v-html、v-text
    <input type="text" v-model="message"/>				// 双向绑定  v-model
    <button v-on:click="handleIncrement"></button>		// 函数绑定  v-on:方法、@方法
    <h1 v-bind:class="{done: item.done}"></h1>			// 属性绑定  v-bind:属性、:属性
    
    <!-- 2种流程语法------------------------------------------->
    <li v-if="show">mess</li>							// 显示隐藏  v-if、v-else-if、v-else、v-show
    <li v-for="item in items">{{item.mess}}</li>		// 循环指令  v-for; item in shuzu、item in obj取v
</div>

补充

数据绑定的补充,插值语法
    <h1>{{ message }}</h1>                   // Mustache语法,可运算
    <h1 v-html=''></h1>                      // 编译内容
    <h1 v-text=''></h1>                      // 不编译内容
    <h1 v-cloak></h1>                        // 解析再显  v-cloak 斗篷,解决js卡顿时用户能看到{{}}的问题
    <h1 v-once>{{ message }}</h1>            // 禁用改变  v-once 只改变一次(不让数据驱动视图)
    <h1 v-pre>{{ message }}</h1>             // 禁用编译  v-pre 文本显示

双向绑定的补充
    多种表单的的绑定
        绑定文本框                           // 返回内容
        绑定单选框                           // (多个绑定同一个变量)返回选中值
        绑定复选框单选                       // 返回布尔
        绑定复选框多选                       // (多个绑定同一个变量)返回数组
        绑定Select单选                      // 返回Value
    修饰符
        v-model.lazy                       // 懒绑定,让input事件更新数据 转换为 回车/失焦时更新数据
        v-model.number                     // 把内容自动转换为数字
        v-model.trim                       // 删除两侧空格

属性绑定的补充,对象语法和数组语法
    对象语 法,后接对象                      :class="{active: true, line: false}"  :style="{font-size: '50px'}"
    数组语法,后接数组                      :class=[actice, 'line']               :style="[{}, {}]"
    也可以接返回对象/数组的函数              :class="getClasses()"

方法绑定的补充,'()'的省略与修饰符
    括号省略
        方法无参时                          // 可省略'()'
        方法有参时                          // 不省略'()'时传递undefine,省略'()'时传递浏览器生成的event时间对象
        event值                            // 也可用'($event)'手动传递,这个值挺有用的:如:event.target.value
    修饰符
        .stop                              // 阻止事件冒泡(嵌套事件监听),Ex:@click.stop=''
        .prevent                           // 阻止默认行为(后接函数以外),Ex:@submit.prevent,@click.stop.prevent=''
        .(键值/别名)                        // 监听指定键盘键帽(键别名/键值)Ex:@keyup.enter='onEnter',@keydown.13='onEnter'
        .native                            // (在组件内才会用到)
        .once                              // 只触发一次回调,Ex:@click.once='doThis'

if补充
    v-if/v-else-if/v-else(整体删减))、v-show(display隐藏)
    Virtual Dom对Dom的复用问题

for补充    
    v-for; (item, index) in shuzu、(value, key, index) in obj
    Virtual Dom对Dom的复用问题。这里建议加key:item
        能更好复用。如数组内插入元素后,原来的dom不会修改