Skip to main content

新增了哪些概念

应用实例

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

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

应用实例并不只限于一个,createApp API 允许在同一个页面中创建多个共存的 Vue 应用。

import { createApp } from 'vue'
// 从一个单文件组件中导入根组件
import App from './App.vue'

const app = createApp(App)

挂载应用

应用实例必须在调用了 .mount() 方法后才会渲染出来。

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

该方法接收一个参数,可以是一个实际的 DOM 元素或是一个 CSS 选择器字符串。

它的返回值是根组件实例而非应用实例。

app.mount('#app')

模板语法

Vue 使用一种基于 HTML 的模板语法,在底层机制中,Vue 会将模板编译成高度优化的 JavaScript 代码。

也可以结合可选的 JSX 支持直接手写渲染函数而不采用模板。但是,这将不会享受到和模板同等级别的编译时优化。

文本插值

最基本的数据绑定形式是文本插值。

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

使用JavaScript表达式

在所有的数据绑定中都支持完整的 JavaScript 表达式。

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

  • 在文本插值中 (双大括号)
  • 在任何 Vue 指令 (以 v- 开头的特殊 attribute) attribute 的值中
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div :id="`list-${id}`"></div>

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

CSS class

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

<div
class="static"
:class="{ active: true, 'text-danger': true }"
></div>
<div :class="[activeClass, errorClass]"></div>
<div :class="[{ active: true }, errorClass]"></div>

CSS style

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

<div :style="{ color: 'red', fontSize: '30px' }"></div>
<div :style="[baseStyles, overridingStyles]"></div>

数组变化侦测

Vue 能够侦听响应式数组的变更方法,并在它们被调用时触发相关的更新。

变更原数组返回新数组
push()filter()
pop()concat()
shift()slice()
unshift()
splice()
sort()
reverse()

Slots

<slot> 元素是一个插槽出口 (slot outlet),标示了父元素提供的插槽内容 (slot content) 将在哪里被渲染。

<script setup>
import FancyButton from './FancyButton.vue'
</script>

<template>
<FancyButton>
Click me <!-- slot content -->
</FancyButton>
</template>
FancyButton.vue
<template>
<button class="fancy-btn">
<slot/> <!-- slot outlet -->
</button>
</template>

具名插槽

带 name 的插槽被称为具名插槽 (named slots)。

要为具名插槽传入内容,需要使用一个含 v-slot 指令的 <template> 元素,并将目标插槽的名字传给该指令。

<BaseLayout>
<template v-slot:header>
<!-- header 插槽的内容放这里 -->
</template>
</BaseLayout>

其中 <template v-slot:header> 可以简写为 <template #header>

BaseLayout.vue
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>

动态插槽名

<BaseLayout>
<template v-slot:[dynamicSlotName]>
...
</template>

<!-- 缩写为 -->
<template #[dynamicSlotName]>
...
</template>
<BaseLayout>

Scoped

使用 scoped 后,父组件的样式将不会渗透到子组件中。

深度选择器

处于 scoped 样式中的选择器如果想要做更深度的选择,即影响到子组件,可以使用 :deep() 这个伪类。

<style scoped>
.a :deep(.b) {
/* ... */
}
</style>

上面的代码会被编译成

.a[data-v-f3f3eg9] .b {
/* ... */
}

插槽选择器

使用 :slotted 伪类以明确地将插槽内容作为选择器的目标。

<style scoped>
:slotted(div) {
color: red;
}
</style>

全局选择器

可以让其中一个样式规则应用到全局。

<style scoped>
:global(.red) {
color: red;
}
</style>

混合使用局部与全局样式

可以在同一个组件中同时包含作用域样式和非作用域样式。

<style>
/* 全局样式 */
</style>

<style scoped>
/* 局部样式 */
</style>