Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/api/composition-api-helpers.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@

- **详细信息**

`useModel()` 可以用于非 SFC 组件,例如在使用原始的 `setup()` 函数时。它预期的第一个参数是 `props` 对象,第二个参数是 model 名称。可选的第三个参数可以用于为生成的 model ref 声明自定义的 getter 和 setter。请注意,与 `defineModel()` 不同,你需要自己声明 props 和 emits。
`useModel()` 可以用于非单文件组件,例如在使用原始的 `setup()` 函数时。它预期的第一个参数是 `props` 对象,第二个参数是 model 名称。可选的第三个参数可以用于为生成的 model ref 声明自定义的 getter 和 setter。请注意,与 `defineModel()` 不同,你需要自己声明 props 和 emits。

## useTemplateRef() <sup class="vt-badge" data-text="3.5+" /> {#usetemplateref}

Expand Down
2 changes: 1 addition & 1 deletion src/api/general.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@
)
```

在将来,我们计划提供一个 Babel 插件,自动推断并注入运行时 props (就像在 SFC 中的 `defineProps` 一样),以便省略运行时 props 的声明。
在将来,我们计划提供一个 Babel 插件,自动推断并注入运行时 props (就像在单文件组件中的 `defineProps` 一样),以便省略运行时 props 的声明。

### webpack Treeshaking 的注意事项 {#note-on-webpack-treeshaking}

Expand Down
2 changes: 1 addition & 1 deletion src/api/options-misc.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

另一种场景是当一个组件通过 [`app.component`](/api/application#app-component) 被全局注册时,这个全局 ID 就自动被设为了其名称。

使用 `name` 选项使你可以覆盖推导出的名称,或是在没有推导出名字时显式提供一个。(例如没有使用构建工具时,或是一个内联的非 SFC 式的组件)
使用 `name` 选项使你可以覆盖推导出的名称,或是在没有推导出名字时显式提供一个。(例如没有使用构建工具时,或是一个内联的非单文件组件)

有一种场景下 `name` 必须是已显式声明的:即 [`<KeepAlive>`](/guide/built-ins/keep-alive) 通过其 `include / exclude` prop 来匹配其需要缓存的组件时。

Expand Down
2 changes: 1 addition & 1 deletion src/api/sfc-script-setup.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# \<script setup> {#script-setup}

`<script setup>` 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。当同时使用 SFC 与组合式 API 时该语法是默认推荐。相比于普通的 `<script>` 语法,它具有更多优势:
`<script setup>` 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。当同时使用单文件组件与组合式 API 时该语法是默认推荐。相比于普通的 `<script>` 语法,它具有更多优势:

- 更少的样板内容,更简洁的代码。
- 能够使用纯 TypeScript 声明 props 和自定义事件。
Expand Down
8 changes: 4 additions & 4 deletions src/api/sfc-spec.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SFC 语法定义 {#sfc-syntax-specification}
# 单文件组件语法定义 {#sfc-syntax-specification}

## 总览 {#overview}

Expand Down Expand Up @@ -58,7 +58,7 @@ export default {

- 每个 `*.vue` 文件可以包含多个 `<style>` 标签。

- 一个 `<style>` 标签可以使用 `scoped` 或 `module` attribute (查看 [SFC 样式功能](/api/sfc-css-features)了解更多细节) 来帮助封装当前组件的样式。使用了不同封装模式的多个 `<style>` 标签可以被混合入同一个组件。
- 一个 `<style>` 标签可以使用 `scoped` 或 `module` attribute (查看[单文件组件样式功能](/api/sfc-css-features)了解更多细节) 来帮助封装当前组件的样式。使用了不同封装模式的多个 `<style>` 标签可以被混合入同一个组件。

### 自定义块 {#custom-blocks}

Expand All @@ -68,11 +68,11 @@ export default {
- [vite-plugin-vue-gql:`<gql>`](https://github.com/wheatjs/vite-plugin-vue-gql)
- [vue-i18n:`<i18n>`](https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n#i18n-custom-block)

自定义块的处理需要依赖工具链。如果你想要在构建中集成你的自定义语块,请参见 [SFC 自定义块集成工具链指南](/guide/scaling-up/tooling#sfc-custom-block-integrations)获取更多细节。
自定义块的处理需要依赖工具链。如果你想要在构建中集成你的自定义语块,请参见[单文件组件自定义块集成工具链指南](/guide/scaling-up/tooling#sfc-custom-block-integrations)获取更多细节。

## 自动名称推导 {#automatic-name-inference}

SFC 在以下场景中会根据**文件名**自动推导其组件名:
单文件组件在以下场景中会根据**文件名**自动推导其组件名:

- 开发警告信息中需要格式化组件名时;
- DevTools 中观察组件时;
Expand Down
2 changes: 1 addition & 1 deletion src/api/utility-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@
:::

:::info 参考
SFC `<style>` 标签支持通过 `v-bind` CSS 函数来链接 CSS 值与组件状态。这允许在没有类型扩展的情况下自定义属性。
单文件组件 `<style>` 标签支持通过 `v-bind` CSS 函数来链接 CSS 值与组件状态。这允许在没有类型扩展的情况下自定义属性。

- [CSS 中的 v-bind()](/api/sfc-css-features#v-bind-in-css)
:::
2 changes: 1 addition & 1 deletion src/glossary/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ Ref 有多种不同的类型。例如,可以使用 `ref()`、`shallowRef()`、

参考:
- [指南 - 单文件组件](/guide/scaling-up/sfc.html)
- [SFC 语法定义](/api/sfc-spec.html)
- [单文件组件语法定义](/api/sfc-spec.html)

## 插槽 (slot) {#slot}

Expand Down
2 changes: 1 addition & 1 deletion src/guide/essentials/component-basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export default {
## 使用组件 {#using-a-component}

:::tip
我们会在接下来的指引中使用 SFC 语法,无论你是否使用构建步骤,组件相关的概念都是相同的。[示例](/examples/)一节中展示了两种场景中的组件使用情况。
我们会在接下来的指引中使用单文件组件语法,无论你是否使用构建步骤,组件相关的概念都是相同的。[示例](/examples/)一节中展示了两种场景中的组件使用情况。
:::

要使用一个子组件,我们需要在父组件中导入它。假设我们把计数器组件放在了一个叫做 `ButtonCounter.vue` 的文件中,这个组件将会以默认导出的形式被暴露给外部。
Expand Down
10 changes: 5 additions & 5 deletions src/guide/extras/reactivity-transform.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ setup(props) {

Vue 为这些宏函数都提供了类型声明 (全局可用),因此类型推导都会符合预期。它与标准的 TypeScript 语义没有不兼容之处,因此它的语法可以与所有现有的工具兼容。

这也意味着这些宏函数在任何 JS / TS 文件中都是合法的,不是仅能在 Vue SFC 中使用
这也意味着这些宏函数在任何 JS / TS 文件中都是合法的,不是仅能在 Vue 单文件组件中使用

因为这些宏函数都是全局可用的,它们的类型需要被显式地引用 (例如,在 `env.d.ts` 文件中):

Expand All @@ -290,8 +290,8 @@ Vue 为这些宏函数都提供了类型声明 (全局可用),因此类型推
### Vite {#vite}

- 需要 `@vitejs/plugin-vue@>=2.0.0`
- 应用于 SFC 和 js(x)/ts(x) 文件。在执行转换之前,会对文件进行快速的使用检查,因此不使用宏的文件不会有性能损失。
- 注意 `reactivityTransform` 现在是一个插件的顶层选项,而不再是位于 `script.refSugar` 之中了,因为它不仅仅只对 SFC 起效
- 应用于单文件组件和 js(x)/ts(x) 文件。在执行转换之前,会对文件进行快速的使用检查,因此不使用宏的文件不会有性能损失。
- 注意 `reactivityTransform` 现在是一个插件的顶层选项,而不再是位于 `script.refSugar` 之中了,因为它不仅仅只对单文件组件起效

```js
// vite.config.js
Expand All @@ -306,7 +306,7 @@ export default {

### `vue-cli` {#vue-cli}

- 目前仅对 SFC 起效
- 目前仅对单文件组件起效
- 需要 `vue-loader@>=17.0.0`

```js
Expand All @@ -328,7 +328,7 @@ module.exports = {

### 仅用 `webpack` + `vue-loader` {#plain-webpack-vue-loader}

- 目前仅对 SFC 起效
- 目前仅对单文件组件起效
- 需要 `vue-loader@>=17.0.0`

```js
Expand Down
10 changes: 5 additions & 5 deletions src/guide/extras/web-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,11 @@ defineCustomElement(MyComponent, {
})
```

### 将 SFC 编译为自定义元素 {#sfc-as-custom-element}
### 将单文件组件编译为自定义元素 {#sfc-as-custom-element}

`defineCustomElement` 也可以搭配 Vue 单文件组件 (SFC) 使用。但是,根据默认的工具链配置,SFC 中的 `<style>` 在生产环境构建时仍然会被抽取和合并到一个单独的 CSS 文件中。当正在使用 SFC 编写自定义元素时,通常需要改为注入 `<style>` 标签到自定义元素的 shadow root 上。
`defineCustomElement` 也可以搭配 Vue 单文件组件 (SFC) 使用。但是,根据默认的工具链配置,SFC 中的 `<style>` 在生产环境构建时仍然会被抽取和合并到一个单独的 CSS 文件中。当正在使用单文件组件编写自定义元素时,通常需要改为注入 `<style>` 标签到自定义元素的 shadow root 上。

官方的 SFC 工具链支持以“自定义元素模式”导入 SFC (需要 `@vitejs/plugin-vue@^1.4.0` 或 `vue-loader@^16.5.0`)。一个以自定义元素模式加载的 SFC 将会内联其 `<style>` 标签为 CSS 字符串,并将其暴露为组件的 `styles` 选项。这会被 `defineCustomElement` 提取使用,并在初始化时注入到元素的 shadow root 上。
官方的单文件组件工具链支持以“自定义元素模式”导入单文件组件 (需要 `@vitejs/plugin-vue@^1.4.0` 或 `vue-loader@^16.5.0`)。一个以自定义元素模式加载的单文件组件将会内联其 `<style>` 标签为 CSS 字符串,并将其暴露为组件的 `styles` 选项。这会被 `defineCustomElement` 提取使用,并在初始化时注入到元素的 shadow root 上。

要开启这个模式,只需要将你的组件文件以 `.ce.vue` 结尾即可:

Expand All @@ -206,7 +206,7 @@ const ExampleElement = defineCustomElement(Example)
customElements.define('my-example', ExampleElement)
```

如果你想要自定义如何判断是否将文件作为自定义元素导入 (例如将所有的 SFC 都视为用作自定义元素),你可以通过给构建插件传递相应插件的 `customElement` 选项来实现:
如果你想要自定义如何判断是否将文件作为自定义元素导入 (例如将所有的单文件组件都视为用作自定义元素),你可以通过给构建插件传递相应插件的 `customElement` 选项来实现:

- [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#using-vue-sfcs-as-custom-elements)
- [vue-loader](https://github.com/vuejs/vue-loader/tree/next#v16-only-options)
Expand Down Expand Up @@ -283,6 +283,6 @@ Vue 的组件模型在设计时同时兼顾了这些需求,因此是一个更

- 贪婪 (eager) 的插槽求值会阻碍组件之间的可组合性。Vue 的[作用域插槽](/guide/components/slots#scoped-slots)是一套强大的组件组合机制,而由于原生插槽的贪婪求值性质,自定义元素无法支持这样的设计。贪婪求值的插槽也意味着接收组件时不能控制何时或是否创建插槽内容的节点。

- 在当下要想使用 shadow DOM 书写局部作用域的 CSS,必须将样式嵌入到 JavaScript 中才可以在运行时将其注入到 shadow root 上。这也导致了 SSR 场景下需要渲染大量重复的样式标签。虽然有一些[平台功能](https://github.com/whatwg/html/pull/4898/)在尝试解决这一领域的问题,但是直到现在还没有达到通用支持的状态,而且仍有生产性能 / SSR 方面的问题需要解决。可与此同时,Vue 的 SFC 本身就提供了 [CSS 局域化机制](/api/sfc-css-features),并支持抽取样式到纯 CSS 文件中。
- 在当下要想使用 shadow DOM 书写局部作用域的 CSS,必须将样式嵌入到 JavaScript 中才可以在运行时将其注入到 shadow root 上。这也导致了 SSR 场景下需要渲染大量重复的样式标签。虽然有一些[平台功能](https://github.com/whatwg/html/pull/4898/)在尝试解决这一领域的问题,但是直到现在还没有达到通用支持的状态,而且仍有生产性能 / SSR 方面的问题需要解决。可与此同时,Vue 的单文件组件本身就提供了 [CSS 局域化机制](/api/sfc-css-features),并支持抽取样式到纯 CSS 文件中。

Vue 将始终紧跟 Web 平台的最新标准,如果平台的新功能能让我们的工作变得更简单,我们将非常乐于利用它们。但是,我们的目标是提供“好用,且现在就能用”的解决方案。这意味着我们在采用新的原生功能时需要保持客观、批判性的态度,并在原生功能完成度不足的时候选择更适当的解决方案。
22 changes: 11 additions & 11 deletions src/guide/scaling-up/sfc.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ const greeting = ref('Hello World!')

</div>

如你所见,Vue 的单文件组件是网页开发中 HTML、CSS 和 JavaScript 三种语言经典组合的自然延伸。`<template>`、`<script>` 和 `<style>` 三个块在同一个文件中封装、组合了组件的视图、逻辑和样式。完整的语法定义可以查阅 [SFC 语法说明](/api/sfc-spec)。
如你所见,Vue 的单文件组件是网页开发中 HTML、CSS 和 JavaScript 三种语言经典组合的自然延伸。`<template>`、`<script>` 和 `<style>` 三个块在同一个文件中封装、组合了组件的视图、逻辑和样式。完整的语法定义可以查阅[单文件组件语法说明](/api/sfc-spec)。

## 为什么要使用 SFC {#why-sfc}
## 为什么要使用单文件组件 {#why-sfc}

使用 SFC 必须使用构建工具,但作为回报带来了以下优点:
使用单文件组件必须使用构建工具,但作为回报带来了以下优点:

- 使用熟悉的 HTML、CSS 和 JavaScript 语法编写模块化的组件
- [让本来就强相关的关注点自然内聚](#what-about-separation-of-concerns)
Expand All @@ -68,17 +68,17 @@ const greeting = ref('Hello World!')
- [更好的 IDE 支持](/guide/scaling-up/tooling#ide-support),提供自动补全和对模板中表达式的类型检查
- 开箱即用的模块热更新 (HMR) 支持

SFC 是 Vue 框架提供的一个功能,并且在下列场景中都是官方推荐的项目组织方式:
单文件组件是 Vue 框架提供的一个功能,并且在下列场景中都是官方推荐的项目组织方式:

- 单页面应用 (SPA)
- 静态站点生成 (SSG)
- 任何值得引入构建步骤以获得更好的开发体验 (DX) 的项目

当然,在一些轻量级场景下使用 SFC 会显得有些杀鸡用牛刀。因此 Vue 同样也可以在无构建步骤的情况下以纯 JavaScript 方式使用。如果你的用例只需要给静态 HTML 添加一些简单的交互,你可以看看 [petite-vue](https://github.com/vuejs/petite-vue),它是一个 6 kB 左右、预优化过的 Vue 子集,更适合渐进式增强的需求。
当然,在一些轻量级场景下使用单文件组件会显得有些杀鸡用牛刀。因此 Vue 同样也可以在无构建步骤的情况下以纯 JavaScript 方式使用。如果你的用例只需要给静态 HTML 添加一些简单的交互,你可以看看 [petite-vue](https://github.com/vuejs/petite-vue),它是一个 6 kB 左右、预优化过的 Vue 子集,更适合渐进式增强的需求。

## SFC 是如何工作的 {#how-it-works}
## 单文件组件是如何工作的 {#how-it-works}

Vue SFC 是一个框架指定的文件格式,因此必须交由 [@vue/compiler-sfc](https://github.com/vuejs/core/tree/main/packages/compiler-sfc) 编译为标准的 JavaScript 和 CSS,一个编译后的 SFC 是一个标准的 JavaScript(ES) 模块,这也意味着在构建配置正确的前提下,你可以像导入其他 ES 模块一样导入 SFC
Vue 单文件组件是一个框架指定的文件格式,因此必须交由 [@vue/compiler-sfc](https://github.com/vuejs/core/tree/main/packages/compiler-sfc) 编译为标准的 JavaScript 和 CSS,一个编译后的单文件组件是一个标准的 JavaScript(ES) 模块,这也意味着在构建配置正确的前提下,你可以像导入其他 ES 模块一样导入单文件组件

```js
import MyComponent from './MyComponent.vue'
Expand All @@ -90,15 +90,15 @@ export default {
}
```

SFC 中的 `<style>` 标签一般会在开发时注入成原生的 `<style>` 标签以支持热更新,而生产环境下它们会被抽取、合并成单独的 CSS 文件。
单文件组件中的 `<style>` 标签一般会在开发时注入成原生的 `<style>` 标签以支持热更新,而生产环境下它们会被抽取、合并成单独的 CSS 文件。

你可以在 [Vue SFC 演练场](https://play.vuejs.org/)中实际使用一下单文件组件,同时可以看到它们最终被编译后的样子。
你可以在 [Vue 单文件组件演练场](https://play.vuejs.org/)中实际使用一下单文件组件,同时可以看到它们最终被编译后的样子。

在实际项目中,我们一般会使用集成了 SFC 编译器的构建工具,比如 [Vite](https://cn.vitejs.dev/) 或者 [Vue CLI](https://cli.vuejs.org/zh/) (基于 [webpack](https://webpack.js.org/)),Vue 官方也提供了脚手架工具来帮助你尽可能快速地上手开发 SFC。更多细节请查看 [SFC 工具链](/guide/scaling-up/tooling)章节。
在实际项目中,我们一般会使用集成了单文件组件编译器的构建工具,比如 [Vite](https://cn.vitejs.dev/) 或者 [Vue CLI](https://cli.vuejs.org/zh/) (基于 [webpack](https://webpack.js.org/)),Vue 官方也提供了脚手架工具来帮助你尽可能快速地上手开发单文件组件。更多细节请查看[单文件组件工具链](/guide/scaling-up/tooling)章节。

## 如何看待关注点分离? {#what-about-separation-of-concerns}

一些有着传统 Web 开发背景的用户可能会因为 SFC 将不同的关注点集合在一处而有所顾虑,觉得 HTML/CSS/JS 应当是分离开的!
一些有着传统 Web 开发背景的用户可能会因为单文件组件将不同的关注点集合在一处而有所顾虑,觉得 HTML/CSS/JS 应当是分离开的!

要回答这个问题,我们必须对这一点达成共识:**前端开发的关注点不是完全基于文件类型分离的**。前端工程化的最终目的都是为了能够更好地维护代码。关注点分离不应该是教条式地将其视为文件类型的区别和分离,仅仅这样并不够帮我们在日益复杂的前端应用的背景下提高开发效率。

Expand Down
2 changes: 1 addition & 1 deletion src/guide/scaling-up/ssr.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ server.get('/', (req, res) => {

从上面的例子到一个生产就绪的 SSR 应用还需要很多工作。我们将需要:

- 支持 Vue SFC 且满足其他构建步骤要求。事实上,我们需要为同一个应用执行两次构建过程:一次用于客户端,一次用于服务器。
- 支持 Vue 单文件组件且满足其他构建步骤要求。事实上,我们需要为同一个应用执行两次构建过程:一次用于客户端,一次用于服务器。

:::tip
Vue 组件用在 SSR 时的编译产物不同——模板被编译为字符串拼接而不是 render 函数,以此提高渲染性能。
Expand Down
Loading
Loading