HTML 的模板语法
,使我们能够 声明式地
将其组件实例的数据绑定到呈现的 DOM 上。
最基本的数据绑定形式是文本插值{{}}
,即双大括号,双大括号里面的值是js表达式
,常见的有:变量、三元表达式等。
<span>Message: {{ msg }}</span>
双大括号标签会被替换为相应组件实例中 msg 属性的值。同时每次 msg 属性更改时它也会同步更新。
模板中的表达式将被沙盒化
,仅能够访问到有限的全局对象列表
。
沙盒化:
将运行的模板隔离在特定的环境中,避免应用的其他模板对改模板造成影响。
全局对象列表中会暴露常用的内置全局对象
,比如 Math 和 Date。没有显式包含在列表中的全局对象将不能在模板内表达式中访问,例如用户附加在 window 上的属性
。然而,你也可以自行在 app.config.globalProperties
上显式地添加它们,供所有的 Vue 表达式使用。
指令是带有 v-
前缀的特殊 attribute。Vue 提供了许多内置指令。
表达式的值变化时响应式地更新 DOM
参数
,在指令名后通过一个冒号
隔开做标识。<a v-bind:href="url"> ... </a>
<a v-on:click="doSomething"> ... </a>
[]
包裹就可以了。<a v-bind:[attributeName]="url"> ... </a>
<!-- 简写 -->
<a :[attributeName]="url"> ... </a>
<a v-on:[eventName]="doSomething"> ... </a>
<!-- 简写 -->
<a @[eventName]="doSomething"> ... </a>
<!-- 这会触发一个编译器警告 -->
<a :['foo' + bar]="value"> ... </a>
如果是直接编写在html中的模板,我们需要避免在名称中使用大写字母,因为浏览器会强制将其转换为小写:
...
面的例子将会在 DOM 内嵌模板中被转换为 :[someattr]。
如果变量的取值是“someAttr”是,将会在 DOM 内嵌模板中被转换为 :someattr。
且你的组件拥有 “someAttr” 属性而非 “someattr”,这段代码将不会工作。
单位文件组件没有此限制
指令也可以添加修饰符,修饰符是是以.
开头的特殊后缀:
<form @submit.prevent="onSubmit">...</form>
.prevent
修饰符会告知 v-on 指令对触发的事件调用 event.preventDefault()
:
用于渲染元素的文本内容。
原理:v-text 通过设置元素的 textContent
属性来工作,因此它将覆盖元素中所有现有的内容
。
<span v-text="msg"></span>
<!-- 等同于 -->
<span>{{msg}}</span>
如果有一个变量存储一段html的字符串,可以被渲染成对应的节点,直接使用文本插值
或v-text
的方法是没有办法将该变量渲染成html片段的
。
这是因为,双大括号会将数据解释为纯文本,而不是 HTML。若想插入 HTML,你需要使用 v-html
指令:
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
在单文件组件,scoped 样式将不会作用于 v-html 里的内容,
因为 HTML 内容不会被 Vue 的模板编译器解析。
可是使用全局的css样式来为v-html中的内容添加样式
动态的绑定一个或多个 attribute
,也可以是组件的 prop
。
当用于组件 props 绑定时,所绑定的 props 必须在子组件中已被正确声明。
使用
在属性名
之前使用 v-bind:
指令,使用该指令表示该属性的属性值是一个js表达式
,js表达式会通过vue实例获取值然后再赋值给该属性:
<div v-bind:id="dynamicId"></div>
单项绑定v-bind:
的作用就是将变量赋值给标签的属性
,同时标签的属性值会随着变量的变化而变化。
响应式
如果通过v-bind绑定的变量是响应式的,那么,当变量修改时就会触发v-bind
重新获取最新的值,将最新的值赋值给属性。从而达到变量值一修改对应的属性值就修改的效果。这种效果正是我们想要的。
因为 v-bind
非常常用,我们提供了特定的简写语法:
, 即v-bind:属性
可以直接简写成:属性
上述案例简写为
<div :id="dynamicId"></div>
如果 attribute 的名称
与绑定的 JavaScript 值的名称
相同,那么可以进一步简化语法,省略 attribute 值:
<!-- 与 :id="id" 相同 -->
<div :id></div>
<!-- 这也同样有效,不简写v-bind,之简写名称 -->
<div v-bind:id></div>
如果一个标签含有多个单项绑定的属性值,可以使用v-bind
的对象模式进行绑定。
eg:
const objectOfAttrs = {
id: 'container',
class: 'wrapper'
}
通过不带参数的v-bind
可以将他们绑定到单个元素上
<div v-bind="objectOfAttrs"></div>
此时div就被绑定了名为id
和class
的了两个属性值
.camel
- 将短横线命名的 attribute 转变为驼峰式命名。
.prop
- 强制绑定为 DOM property。
.attr
- 强制绑定为 DOM attribute。
作为prop使用的时候可以简写成.
<div :someProperty.prop="someObject">div>
<div .someProperty="someObject">div>
在表单输入元素或组件上创建双向绑定。也需要指定属性值,一般属性值就是value
,绑定格式是v-model:value="绑定的值"
<input v-model:value="model" />
因为绑定的属性值一般都是value
,所以value
可以简写
<input v-model="model" />
双向绑定带来的效果是:当表单元素绑定的值修改,页面上表单的输入值也会修改(v-bind也能实现);而且当页面表单的输入只修改后,表单元素绑定的值也会修改(v-bind无法实现)。
.lazy
- 监听 change 事件而不是 input.number
- 将输入的合法字符串转为数字.trim
- 移除输入内容两端空格v-model
的使用仅限输入组件
基于表达式值的真假性,来改变元素的可见性。
原理:v-show 通过设置内联样式的 display CSS 属性来工作。当条件改变时,也会触发过渡效果。
基于表达式值的真假性,来条件性地渲染元素。
原理:当 v-if 元素被触发,元素及其所包含的指令/组件都会销毁和重构。如果初始条件是假,那么其内部的内容根本都不会被渲染。
所以v-show
和v-if
的区别是:
v-if会销毁元素,v-show只是修改元素的属性。
如果需要频繁切换显示状态,v-show效率更高。如果元素可能永远都不需要被显示出来,那就使用v-if。
表示 v-if 链式调用的else 块
,无需传入表达式。
限定:上一个兄弟元素必须有 v-if
或 v-else-if
。
<div v-if="Math.random() > 0.5">
Now you see me
</div>
<div v-else>
Now you don't
</div>
表示 v-if 的else if 块
。可以进行链式调用。
限定:上一个兄弟元素必须有 v-if
或 v-else-if
。
基于原始数据多次渲染元素或模板块。
<div v-for="(item, index) in array"></div>
<div v-for="(value, key) in object"></div>
当同时使用 v-if
和 v-for
时 , v-if 比 v-for 优先级更高
。我们并不推荐在一元素上同时使用这两个指令 。
给元素绑定事件监听器。事件类型由参数来指定。
<!-- 方法处理函数 -->
<button v-on:click="doThis"></button>
v-on:
可以简写成@
<!-- 方法处理函数 -->
<button @click="doThis"></button>
.stop
- 调用 event.stopPropagation(),阻止冒泡。.prevent
- 调用 event.preventDefault(),阻止默认事件。.capture
- 在捕获模式添加事件监听器。.self
- 只有事件从元素本身发出才触发处理函数。.{keyAlias}
- 只在某些按键下触发处理函数。.once
- 最多触发一次处理函数。.left
- 只在鼠标左键事件触发处理函数。.right
- 只在鼠标右键事件触发处理函数。.middle
- 只在鼠标中键事件触发处理函数。.passive
- 通过 { passive: true } 附加一个 DOM 事件。
<button @click.stop="doThis">button>
<button @click.prevent="doThis">button>
<form @submit.prevent>form>
<button @click.stop.prevent="doThis">button>
<input @keyup.enter="onEnter" />
事件名对应的变量用[]
括起来
<button v-on:[event]="doThis">button>
<button @[event]="doThis">button>
用于声明具名插槽
或是期望接收 props 的作用域插槽
。
插槽的使用方法,可以点这里进行查看
标签上使用。
<BaseLayout>
<template v-slot:header>
Header content
template>
<template v-slot:default>
Default slot content
template>
<template v-slot:footer>
Footer content
template>
BaseLayout>
<InfiniteScroll>
<template v-slot:item="slotProps">
<div class="item">
{{ slotProps.item.text }}
div>
template>
InfiniteScroll>
<Mouse v-slot="{ x, y }">
Mouse position: {{ x }}, {{ y }}
Mouse>
跳过该元素及其所有子元素的编译。
元素内具有 v-pre,所有 Vue 模板语法都会被保留并按原样渲染
:如果变迁中有插值语法{{}}
,就会显示原始双大括号标签及内容。
<span v-pre>{{ this will not be compiled }}</span>
仅渲染元素和组件一次,并跳过之后的更新。
在随后的重新渲染,元素/组件及其所有子项将被当作静态内容并跳过渲染。这可以用来优化更新时的性能。
<span v-once>This will never change: {{msg}}span>
<div v-once>
<h1>commenth1>
<p>{{msg}}p>
div>
<MyComponent v-once :comment="msg" />
<ul>
<li v-for="i in list" v-once>{{i}}li>
ul>
用来缓存一个模板的子树。在元素和组件上都可以使用。
为了实现缓存,该指令需要传入一个固定长度的依赖值数组
进行比较。如果数组里的每个值
都与最后一次的渲染
相同,那么整个子树的更新将被跳过。
举例来说:
<div v-memo="[valueA, valueB]">
...
</div>
当组件重新渲染,如果 valueA 和 valueB 都保持不变,这个 v-memo 传入空依赖数组 (v-memo=“[]”) 将与 v-once 效果相同。 v-memo 仅用于性能至上场景中的微小优化,应该很少需要。最常见的情况可能是有助于渲染 默认情况下,当组件的 selected 状态改变,就会重新渲染,默认会重新创建大量的 vnode,尽管绝大部分都跟之前是一模一样的。 用于隐藏尚未完成编译的DOM模板。 问题: 当使用直接在 DOM 中书写的模板时,可能会出现一种叫做“未编译模板闪现”的情况:用户可能先看到的是还没编译完成的双大括号标签,直到挂载的组件将它们替换为实际渲染的内容。 解决: v-cloak可以解决这一问题, 直到编译完成前,与 v-for 一起使用
海量 v-for
列表 (长度超过 1000 的情况):<div v-for="item in list" :key="item.id" v-memo="[item.id === selected]">
<p>ID: {{ item.id }} - selected: {{ item.id === selected }}p>
<p>...more child nodesp>
div>
v-memo 用在这里本质上是在说:“只有当该项的被选中状态改变时才需要更新”。
当搭配 v-for 使用 v-memo,确保两者都绑定在同一个元素上。v-memo 不能用在 v-for 内部。v-cloak
v-cloak
在模板编译之前
会保留在所绑定的元素上,直到相关组件实例被挂载后才移除。一般v-clock
有一个对应的[v-clock]
样式,通过该样式编写该模块在编译完成之前显示的内容。<div v-cloak>
{{ message }}
div>
[v-cloak] {
display: none;
}