目录

创建一个 Vue 应用#

应用实例#

根组件#

挂载应用#

DOM 中的根组件模板#

应用配置#

多个应用实例#

模板语法#

文本插值#

原始 HTML#

Attribute 绑定#

简写#

布尔型 Attribute#

动态绑定多个值#

使用 JavaScript 表达式#

仅支持表达式#

调用函数#

受限的全局访问#

指令 Directives#

参数 Arguments#

动态参数#

修饰符 Modifiers#

响应式基础#

声明响应式状态#

响应式代理 vs. 原始值#

声明方法#

DOM 更新时机#

深层响应性#

有状态方法#

计算属性#

基础示例#

计算属性缓存 vs 方法#

可写计算属性#

最佳实践#

Getter 不应有副作用#

避免直接修改计算属性值#

Class 与 Style 绑定#

绑定 HTML class#

绑定对象#

绑定数组#

在组件上使用#

绑定内联样式#

绑定对象#

绑定数组#

自动前缀#

样式多值#

条件渲染#

v-if#

v-else#

Vue is awesome!

v-else-if#

上的 v-if#

创建一个 Vue 应用#

应用实例#

每个 Vue 应用都是通过 createApp 函数创建一个新的 应用实例

js

import { createApp } from 'vue'
​
const app = createApp({/* 根组件选项 */
})

根组件#

我们传入 createApp 的对象实际上是一个组件,每个应用都需要一个“根组件”,其他组件将作为其子组件。

如果你使用的是单文件组件,我们可以直接从另一个文件中导入根组件。

js

import { createApp } from 'vue'
// 从一个单文件组件中导入根组件
import App from './App.vue'
​
const app = createApp(App)

虽然本指南中的许多示例只需要一个组件,但大多数真实的应用都是由一棵嵌套的、可重用的组件树组成的。例如,一个待办事项 (Todos) 应用的组件树可能是这样的:

App (root component)
├─ TodoList
│  └─ TodoItem
│     ├─ TodoDeleteButton
│     └─ TodoEditButton
└─ TodoFooter├─ TodoClearButton└─ TodoStatistics

我们会在指南的后续章节中讨论如何定义和组合多个组件。在那之前,我们得先关注一个组件内到底发生了什么。

挂载应用#

应用实例必须在调用了 .mount() 方法后才会渲染出来。该方法接收一个“容器”参数,可以是一个实际的 DOM 元素或是一个 CSS 选择器字符串:

html

<div id="app"></div>

js

app.mount('#app')

应用根组件的内容将会被渲染在容器元素里面。容器元素自己将不会被视为应用的一部分。

.mount() 方法应该始终在整个应用配置和资源注册完成后被调用。同时请注意,不同于其他资源注册方法,它的返回值是根组件实例而非应用实例。

DOM 中的根组件模板#

当在未采用构建流程的情况下使用 Vue 时,我们可以在挂载容器中直接书写根组件模板:

html

<div id="app"><button @click="count++">{{ count }}</button>
</div>

js

import { createApp } from 'vue'
​
const app = createApp({data() {return {count: 0}}
})
​
app.mount('#app')

当根组件没有设置 template 选项时,Vue 将自动使用容器的 innerHTML 作为模板。

应用配置#

应用实例会暴露一个 .config 对象允许我们配置一些应用级的选项,例如定义一个应用级的错误处理器,用来捕获所有子组件上的错误:

js

app.config.errorHandler = (err) => {/* 处理错误 */
}

应用实例还提供了一些方法来注册应用范围内可用的资源,例如注册一个组件:

js

app.component('TodoDeleteButton', TodoDeleteButton)

这使得 TodoDeleteButton 在应用的任何地方都是可用的。我们会在指南的后续章节中讨论关于组件和其他资源的注册。你也可以在 API 参考中浏览应用实例 API 的完整列表。

确保在挂载应用实例之前完成所有应用配置!

多个应用实例#

应用实例并不只限于一个。createApp API 允许你在同一个页面中创建多个共存的 Vue 应用,而且每个应用都拥有自己的用于配置和全局资源的作用域。

js

const app1 = createApp({/* ... */
})
app1.mount('#container-1')
​
const app2 = createApp({/* ... */
})
app2.mount('#container-2')

如果你正在使用 Vue 来增强服务端渲染 HTML,并且只想要 Vue 去控制一个大型页面中特殊的一小部分,应避免将一个单独的 Vue 应用实例挂载到整个页面上,而是应该创建多个小的应用实例,将它们分别挂载到所需的元素上去。

模板语法#

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

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

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

文本插值#

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

template

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

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

原始 HTML#

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

template

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

Using text interpolation: This should be red.

Using v-html directive: This should be red.

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

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

安全警告

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

Attribute 绑定#

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

template

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

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

简写#

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

template

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

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

接下来的指引中,我们都将在示例中使用简写语法,因为这是在实际开发中更常见的用法。

布尔型 Attribute#

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

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

template

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

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

动态绑定多个值#

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

js

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

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

template

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

使用 JavaScript 表达式#

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

template

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

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

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

  • 在文本插值中 (双大括号)

  • 在任何 Vue 指令 (以 v- 开头的特殊 attribute) attribute 的值中

仅支持表达式#

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

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

template

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

调用函数#

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

template

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

TIP

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

受限的全局访问#

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

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

指令 Directives#

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

指令 attribute 的期望值为一个 JavaScript 表达式 (除了少数几个例外,即之后要讨论到的 v-forv-onv-slot)。一个指令的任务是在其表达式的值变化时响应式地更新 DOM。以 v-if 为例:

template

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

这里,v-if 指令会基于表达式 seen 的值的真假来移除/插入该 <p> 元素。

参数 Arguments#

某些指令会需要一个“参数”,在指令名后通过一个冒号隔开做标识。例如用 v-bind 指令来响应式地更新一个 HTML attribute:

template

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

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

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

template

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

这里的参数是要监听的事件名称:clickv-on 有一个相应的缩写,即 @ 字符。我们之后也会讨论关于事件处理的更多细节。

动态参数#

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

template

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

这里的 attributeName 会作为一个 JavaScript 表达式被动态执行,计算得到的值会被用作最终的参数。举例来说,如果你的组件实例有一个数据属性 attributeName,其值为 "href",那么这个绑定就等价于 v-bind:href

相似地,你还可以将一个函数绑定到动态的事件名称上:

template

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

在此示例中,当 eventName 的值是 "focus" 时,v-on:[eventName] 就等价于 v-on:focus

动态参数值的限制#

动态参数中表达式的值应当是一个字符串,或者是 null。特殊值 null 意为显式移除该绑定。其他非字符串的值会触发警告。

动态参数语法的限制#

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

template

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

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

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

template

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

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

修饰符 Modifiers#

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

template

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

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

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

响应式基础#

API 参考

本页和后面很多页面中都分别包含了选项式 API 和组合式 API 的示例代码。现在你选择的是 选项式 API。你可以使用左侧侧边栏顶部的 “API 风格偏好” 开关在 API 风格之间切换。

声明响应式状态#

选用选项式 API 时,会用 data 选项来声明组件的响应式状态。此选项的值应为返回一个对象的函数。Vue 将在创建新组件实例的时候调用此函数,并将函数返回的对象用响应式系统进行包装。此对象的所有顶层属性都会被代理到组件实例 (即方法和生命周期钩子中的 this) 上。

js

export default {data() {return {count: 1}},// `mounted` 是生命周期钩子,之后我们会讲到mounted() {// `this` 指向当前组件实例console.log(this.count) // => 1// 数据属性也可以被更改this.count = 2}
}

在演练场中尝试一下

这些实例上的属性仅在实例首次创建时被添加,因此你需要确保它们都出现在 data 函数返回的对象上。若所需的值还未准备好,在必要时也可以使用 nullundefined 或者其他一些值占位。

虽然也可以不在 data 上定义,直接向组件实例添加新属性,但这个属性将无法触发响应式更新。

Vue 在组件实例上暴露的内置 API 使用 $ 作为前缀。它同时也为内部属性保留 _ 前缀。因此,你应该避免在顶层 data 上使用任何以这些字符作前缀的属性。

响应式代理 vs. 原始值#

在 Vue 3 中,数据是基于 JavaScript Proxy(代理) 实现响应式的。使用过 Vue 2 的用户可能需要注意下面这样的边界情况:

js

export default {data() {return {someObject: {}}},mounted() {const newObject = {}this.someObject = newObjectconsole.log(newObject === this.someObject) // false}
}

当你在赋值后再访问 this.someObject,此值已经是原来的 newObject 的一个响应式代理。与 Vue 2 不同的是,这里原始的 newObject 不会变为响应式:请确保始终通过 this 来访问响应式状态。

声明方法#

在 Vue School 上观看免费课程

要为组件添加方法,我们需要用到 methods 选项。它应该是一个包含所有方法的对象:

js

export default {data() {return {count: 0}},methods: {increment() {this.count++}},mounted() {// 在其他方法或是生命周期中也可以调用方法this.increment()}
}

Vue 自动为 methods 中的方法绑定了永远指向组件实例的 this。这确保了方法在作为事件监听器或回调函数时始终保持正确的 this。你不应该在定义 methods 时使用箭头函数,因为箭头函数没有自己的 this 上下文。

js

export default {methods: {increment: () => {// 反例:无法访问此处的 `this`!}}
}

和组件实例上的其他属性一样,方法也可以在模板上被访问。在模板中它们常常被用作事件监听器:

template

<button @click="increment">{{ count }}</button>

在演练场中尝试一下

在上面的例子中,increment 方法会在 <button> 被点击时调用。

DOM 更新时机#

当你更改响应式状态后,DOM 会自动更新。然而,你得注意 DOM 的更新并不是同步的。相反,Vue 将缓冲它们直到更新周期的 “下个时机” 以确保无论你进行了多少次状态更改,每个组件都只更新一次。

若要等待一个状态改变后的 DOM 更新完成,你可以使用 nextTick() 这个全局 API:

js

import { nextTick } from 'vue'export default {methods: {increment() {this.count++nextTick(() => {// 访问更新后的 DOM})}}
}

深层响应性#

在 Vue 中,状态都是默认深层响应式的。这意味着即使在更改深层次的对象或数组,你的改动也能被检测到。

js

export default {data() {return {obj: {nested: { count: 0 },arr: ['foo', 'bar']}}},methods: {mutateDeeply() {// 以下都会按照期望工作this.obj.nested.count++this.obj.arr.push('baz')}}
}

你也可以直接创建一个浅层响应式对象。它们仅在顶层具有响应性,一般仅在某些特殊场景中需要。

有状态方法#

在某些情况下,我们可能需要动态地创建一个方法函数,比如创建一个预置防抖的事件处理器:

js

import { debounce } from 'lodash-es'export default {methods: {// 使用 Lodash 的防抖函数click: debounce(function () {// ... 对点击的响应 ...}, 500)}
}

不过这种方法对于被重用的组件来说是有问题的,因为这个预置防抖的函数是 有状态的:它在运行时维护着一个内部状态。如果多个组件实例都共享这同一个预置防抖的函数,那么它们之间将会互相影响。

要保持每个组件实例的防抖函数都彼此独立,我们可以改为在 created 生命周期钩子中创建这个预置防抖的函数:

js

export default {created() {// 每个实例都有了自己的预置防抖的处理函数this.debouncedClick = _.debounce(this.click, 500)},unmounted() {// 最好是在组件卸载时// 清除掉防抖计时器this.debouncedClick.cancel()},methods: {click() {// ... 对点击的响应 ...}}
}

计算属性#

在 Vue School 上观看免费课程

基础示例#

模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。比如说,我们有这样一个包含嵌套数组的对象:

js

export default {data() {return {author: {name: 'John Doe',books: ['Vue 2 - Advanced Guide','Vue 3 - Basic Guide','Vue 4 - The Mystery']}}}
}

我们想根据 author 是否已有一些书籍来展示不同的信息:

template

<p>Has published books:</p>
<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>

这里的模板看起来有些复杂。我们必须认真看好一会儿才能明白它的计算依赖于 author.books。更重要的是,如果在模板中需要不止一次这样的计算,我们可不想将这样的代码在模板里重复好多遍。

因此我们推荐使用计算属性来描述依赖响应式状态的复杂逻辑。这是重构后的示例:

js

export default {data() {return {author: {name: 'John Doe',books: ['Vue 2 - Advanced Guide','Vue 3 - Basic Guide','Vue 4 - The Mystery']}}},computed: {// 一个计算属性的 getterpublishedBooksMessage() {// `this` 指向当前组件实例return this.author.books.length > 0 ? 'Yes' : 'No'}}
}

template

<p>Has published books:</p>
<span>{{ publishedBooksMessage }}</span>

在演练场中尝试一下

我们在这里定义了一个计算属性 publishedBooksMessage

更改此应用的 databooks 数组的值后,可以看到 publishedBooksMessage 也会随之改变。

在模板中使用计算属性的方式和一般的属性并无二致。Vue 会检测到 this.publishedBooksMessage 依赖于 this.author.books,所以当 this.author.books 改变时,任何依赖于 this.publishedBooksMessage 的绑定都将同时更新。

也可参考:为计算属性标记类型

计算属性缓存 vs 方法#

你可能注意到我们在表达式中像这样调用一个函数也会获得和计算属性相同的结果:

template

<p>{{ calculateBooksMessage() }}</p>

js

// 组件中
methods: {calculateBooksMessage() {return this.author.books.length > 0 ? 'Yes' : 'No'}
}

若我们将同样的函数定义为一个方法而不是计算属性,两种方式在结果上确实是完全相同的,然而,不同之处在于计算属性值会基于其响应式依赖被缓存。一个计算属性仅会在其响应式依赖更新时才重新计算。这意味着只要 author.books 不改变,无论多少次访问 publishedBooksMessage 都会立即返回先前的计算结果,而不用重复执行 getter 函数。

这也解释了为什么下面的计算属性永远不会更新,因为 Date.now() 并不是一个响应式依赖:

js

computed: {now() {return Date.now()}
}

相比之下,方法调用总是会在重渲染发生时再次执行函数。

为什么需要缓存呢?想象一下我们有一个非常耗性能的计算属性 list,需要循环一个巨大的数组并做许多计算逻辑,并且可能也有其他计算属性依赖于 list。没有缓存的话,我们会重复执行非常多次 list 的 getter,然而这实际上没有必要!如果你确定不需要缓存,那么也可以使用方法调用。

可写计算属性#

计算属性默认是只读的。当你尝试修改一个计算属性时,你会收到一个运行时警告。只在某些特殊场景中你可能才需要用到“可写”的属性,你可以通过同时提供 getter 和 setter 来创建:

js

export default {data() {return {firstName: 'John',lastName: 'Doe'}},computed: {fullName: {// getterget() {return this.firstName + ' ' + this.lastName},// setterset(newValue) {// 注意:我们这里使用的是解构赋值语法[this.firstName, this.lastName] = newValue.split(' ')}}}
}

现在当你再运行 this.fullName = 'John Doe' 时,setter 会被调用而 this.firstNamethis.lastName 会随之更新。

最佳实践#

Getter 不应有副作用#

计算属性的 getter 应只做计算而没有任何其他的副作用,这一点非常重要,请务必牢记。举例来说,不要在 getter 中做异步请求或者更改 DOM!一个计算属性的声明中描述的是如何根据其他值派生一个值。因此 getter 的职责应该仅为计算和返回该值。在之后的指引中我们会讨论如何使用监听器根据其他响应式状态的变更来创建副作用。

避免直接修改计算属性值#

从计算属性返回的值是派生状态。可以把它看作是一个“临时快照”,每当源状态发生变化时,就会创建一个新的快照。更改快照是没有意义的,因此计算属性的返回值应该被视为只读的,并且永远不应该被更改——应该更新它所依赖的源状态以触发新的计算。

Class 与 Style 绑定#

数据绑定的一个常见需求场景是操纵元素的 CSS class 列表和内联样式。因为 classstyle 都是 attribute,我们可以和其他 attribute 一样使用 v-bind 将它们和动态的字符串绑定。但是,在处理比较复杂的绑定时,通过拼接生成字符串是麻烦且易出错的。因此,Vue 专门为 classstylev-bind 用法提供了特殊的功能增强。除了字符串外,表达式的值也可以是对象或数组。

绑定 HTML class#

在 Vue School 上观看免费课程

绑定对象#

我们可以给 :class (v-bind:class 的缩写) 传递一个对象来动态切换 class:

template

<div :class="{ active: isActive }"></div>

上面的语法表示 active 是否存在取决于数据属性 isActive 的真假值。

你可以在对象中写多个字段来操作多个 class。此外,:class 指令也可以和一般的 class attribute 共存。举例来说,下面这样的状态:

js

data() {return {isActive: true,hasError: false}
}

配合以下模板:

template

<divclass="static":class="{ active: isActive, 'text-danger': hasError }"
></div>

渲染的结果会是:

template

<div class="static active"></div>

isActive 或者 hasError 改变时,class 列表会随之更新。举例来说,如果 hasError 变为 true,class 列表也会变成 "static active text-danger"

绑定的对象并不一定需要写成内联字面量的形式,也可以直接绑定一个对象:

js

data() {return {classObject: {active: true,'text-danger': false}}
}

template

<div :class="classObject"></div>

这也会渲染出相同的结果。我们也可以绑定一个返回对象的计算属性。这是一个常见且很有用的技巧:

js

data() {return {isActive: true,error: null}
},
computed: {classObject() {return {active: this.isActive && !this.error,'text-danger': this.error && this.error.type === 'fatal'}}
}

template

<div :class="classObject"></div>

绑定数组#

我们可以给 :class 绑定一个数组来渲染多个 CSS class:

js

data() {return {activeClass: 'active',errorClass: 'text-danger'}
}

template

<div :class="[activeClass, errorClass]"></div>

渲染的结果是:

template

<div class="active text-danger"></div>

如果你也想在数组中有条件地渲染某个 class,你可以使用三元表达式:

template

<div :class="[isActive ? activeClass : '', errorClass]"></div>

errorClass 会一直存在,但 activeClass 只会在 isActive 为真时才存在。

然而,这可能在有多个依赖条件的 class 时会有些冗长。因此也可以在数组中嵌套对象:

template

<div :class="[{ active: isActive }, errorClass]"></div>

在组件上使用#

本节假设你已经有 Vue 组件的知识基础。如果没有,你也可以暂时跳过,以后再阅读。

对于只有一个根元素的组件,当你使用了 class attribute 时,这些 class 会被添加到根元素上,并与该元素上已有的 class 合并。

举例来说,如果你声明了一个组件名叫 MyComponent,模板如下:

template

<!-- 子组件模板 -->
<p class="foo bar">Hi!</p>

在使用时添加一些 class:

template

<!-- 在使用组件时 -->
<MyComponent class="baz boo" />

渲染出的 HTML 为:

template

<p class="foo bar baz boo">Hi</p>

Class 的绑定也是同样的:

template

<MyComponent :class="{ active: isActive }" />

isActive 为真时,被渲染的 HTML 会是:

template

<p class="foo bar active">Hi</p>

如果你的组件有多个根元素,你将需要指定哪个根元素来接收这个 class。你可以通过组件的 $attrs 属性来实现指定:

template

<!-- MyComponent 模板使用 $attrs 时 -->
<p :class="$attrs.class">Hi!</p>
<span>This is a child component</span>

template

<MyComponent class="baz" />

这将被渲染为:

html

<p class="baz">Hi!</p>
<span>This is a child component</span>

你可以在透传 Attribute 一章中了解更多组件的 attribute 继承的细节。

绑定内联样式#

绑定对象#

:style 支持绑定 JavaScript 对象值,对应的是 HTML 元素的 style 属性:

js

data() {return {activeColor: 'red',fontSize: 30}
}

template

<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

尽管推荐使用 camelCase,但 :style 也支持 kebab-cased 形式的 CSS 属性 key (对应其 CSS 中的实际名称),例如:

template

<div :style="{ 'font-size': fontSize + 'px' }"></div>

直接绑定一个样式对象通常是一个好主意,这样可以使模板更加简洁:

js

data() {return {styleObject: {color: 'red',fontSize: '13px'}}
}

template

<div :style="styleObject"></div>

同样的,如果样式对象需要更复杂的逻辑,也可以使用返回样式对象的计算属性。

绑定数组#

我们还可以给 :style 绑定一个包含多个样式对象的数组。这些对象会被合并后渲染到同一元素上:

template

<div :style="[baseStyles, overridingStyles]"></div>

自动前缀#

当你在 :style 中使用了需要浏览器特殊前缀的 CSS 属性时,Vue 会自动为他们加上相应的前缀。Vue 是在运行时检查该属性是否支持在当前浏览器中使用。如果浏览器不支持某个属性,那么将尝试加上各个浏览器特殊前缀,以找到哪一个是被支持的。

样式多值#

你可以对一个样式属性提供多个 (不同前缀的) 值,举例来说:

template

<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>

数组仅会渲染浏览器支持的最后一个值。在这个示例中,在支持不需要特别前缀的浏览器中都会渲染为 display: flex

条件渲染#

在 Vue School 上观看免费课程

v-if#

v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回真值时才被渲染。

template

<h1 v-if="awesome">Vue is awesome!</h1>

v-else#

你也可以使用 v-elsev-if 添加一个“else 区块”。

template

<button @click="awesome = !awesome">Toggle</button><h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 												

VUE.js中文官方文档相关推荐

  1. dubbo官方文档中文_Pandas中文官方文档:基础用法5

    本文授权转载自Python大咖谈禁止二次转载 大家好,我是老表 阅读文本大概需要 16 分钟 建议从头开始学习,本系列前四篇 Pandas中文官方文档:基础用法1 Pandas中文官方文档:基础用法2 ...

  2. python官方文档中文下载-python中文官方文档 PDF 下载

    Python 2 教程 Python是一门简单易学,功能强大的编程语言.它具有高效的高级数据结构和简单而有效的 面向对象编程方法.Python优雅的语法和动态类型以及其解释性的性质,使它在许多领域和 ...

  3. Dubbo中文官方文档

    Dubbo中文官方文档 由于市面并没有dubbo相关的书籍,最好的自学方式除了看教学视频就只能看官方文档了,小伙伴找不到中文官方文档的,可以用我的url,一起学习! http://dubbo.apac ...

  4. springboot中文官方文档

    springboot中文官方文档 https://www.breakyizhan.com/springboot/3028.html spring框架 https://www.breakyizhan.c ...

  5. opencv4.1中文官方文档

    我用阿里云盘分享了「opencv 4.1中文官方文档v1.1版.pdf」,你可以不限速下载

  6. Spring Framework 中文官方文档

    Spring Framework 中文官方文档 目前为最新版 5.3.11. 其他spring文档不断更新中 1.历史.设计理念.反馈.入门. Overview 2.IoC 容器.事件.资源.i18n ...

  7. k8s1.18多master节点高可用集群安装-超详细中文官方文档

    kubernetes安装系列文章 kubernetes1.17.3安装-超详细的安装步骤 安装kubernetes1.17.3多master节点的高可用集群 k8s1.18单master节点高可用集群 ...

  8. vue3.0(包含中文官方文档)

    vue3.0 官方文档 一.工程创建 1.安装node 2. 安装vue3.0 方式一:npm i -g @vue/cli 方式二:cnpm install -g @vue/cli 这个需要安装淘宝镜 ...

  9. IntelliJ IDEA 中文官方文档

    目录 认识IntelliJ IDEA IntelliJ IDEA 安装和设置 IntelliJ IDEA如何使用 IntelliJ IDEA中不容错过的快捷键 IntelliJ IDEA专业的使用技巧 ...

最新文章

  1. 组织级项目管理实例分享——来自项目管理群的讨论
  2. 【日记】一次程序调优发现的同步IO写的问题,切记
  3. MySQL INT、TINYINT、SMALLINT、MEDIUMINT、BIGINT(整数类型)
  4. 更改c语言程序保存地址吗,C语言文本文件实现局部修改
  5. mybatis-plus代码生成器使用和代码
  6. boost::multiprecision模块实现MPC后端对多精度复数的使用的测试程序
  7. Dreamweaver PHP代码护眼配色方案
  8. 【Pytorch神经网络理论篇】 27 图神经网络DGL库:简介+安装+卸载+数据集+PYG库+NetWorkx库
  9. 32 SD配置-合作伙伴确认-设置客户主数据的合作伙伴确定
  10. hive修改默认创建表格式
  11. POJ 3421 X-factor Chains
  12. sql语句查询执行顺序
  13. mysql date 索引_SQL 中 IS NULL 可以走索引
  14. gradle配置阿里Maven仓库
  15. McAfee VirusScan Enterprise
  16. 屏幕录像专家录制视频时不能全屏
  17. ​手机APP应用软件开发
  18. 基础linux命令详情
  19. Redis数据结构之hash对象
  20. 赛博哈希CyberHash顺势而为,获数千万美金的融资

热门文章

  1. java商城并发_一次线上商城系统高并发优化,涨姿势了~
  2. 完美破解C# DLL
  3. Myeclipse tomcat 部署项目报错
  4. 一个简单的三维向量类
  5. 如何拍摄优质的餐饮宣传片之文案篇
  6. 游戏是如何让你上瘾的
  7. 求助,wifi无ip分配怎么处理
  8. 订单模块业务处理流程梳理记录
  9. ABAP项目砖家之旅-ABAP对象命名规则
  10. 数字化绿色化协同发展白皮书