diff --git a/package.json b/package.json index dfb21e48d..957186cab 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "dev": "vitepress", "build": "vitepress build", "preview": "vitepress preview", - "lint": "zhlint 'src/{api,about,guide,sponsor,translations,tutorial}/**/*.md'", + "lint": "zhlint \"src/{api,about,guide,sponsor,translations,tutorial}/**/*.md\"", "clean": "rm -rf .vitepress/dist", "sync": "node scripts/sync.js", "preinstall": "npx only-allow pnpm", diff --git a/src/about/translation.md b/src/about/translation.md index 0c1ddc85f..ae4989759 100644 --- a/src/about/translation.md +++ b/src/about/translation.md @@ -31,7 +31,7 @@ aside: deep 但也有例外的情况,某些英文单词我们倾向于选择不翻译、用原词。开发者常常与一部分英语单词打交道,许多英语单词甚至作为了开发框架或操作系统的专有名词,直接抛出这个单词也的确能够帮助用户更好的理解、锁定所讲的是什么概念。 -3. **更符合中文的表述方式**:我们必须正视英语和中文本身的差异与不同,由于表达方式和语法结构的区别,常常一个结构复杂的多重定语从句很难逐字逐词地直译成中文,翻译出的句子应符合母语者的叙述习惯,即尽可能避免英语式的倒装(哪怕讲述方式与作者原文有较大区别),表述尽可能口语化。最好的方式应该是将视线从单个句子中移出来,结合上下文先进行理解再用中文的习惯性表达将其重新复述出来。 +3. **更符合中文的表述方式**:我们必须正视英语和中文本身的差异与不同,由于表达方式和语法结构的区别,常常一个结构复杂的多重定语从句很难逐字逐词地直译成中文,翻译出的句子应符合母语者的叙述习惯,即尽可能避免英语式的倒装(哪怕讲述方式与作者原文有较大区别),表述尽可能口语化。最好的方式应该是将视线从单个句子中移出来,结合上下文先进行理解再用中文的习惯性表达将其重新复述出来。 ## 格式规范 @@ -90,12 +90,12 @@ aside: deep - 逗号、句号、分号、冒号、叹号、问号,统一使用全角字符:,。;:!? - 破折号使用:—— - 引号统一使用 “ ” 和 ‘ ’ -- 括号统一使用全角括号 () +- 括号统一使用半角括号 () - 非注释部分的代码除外,保留英文标点符号。 #### 内联代码或代码关键字 -- 务必用反引号(即英文输入法下,按键盘上 Tab 键上方的那个键)将内容括起来。 +- 务必用反引号(即英文输入法下,按键盘上 Tab 键上方的那个键)将内容括起来。 - 包括代码注释中出现代码或代码关键字时,也要括起来。 #### 空格的使用 @@ -256,7 +256,7 @@ Vitepress 和 Vuepress 中对以上两种写法的渲染视觉效果为: 在 Markdown 文档中 `[title](link)` 形式的链接非常常用,而 Vue 文档中大量使用了这一语法,用来作章节的跳转。 -链接中有时还会带有锚点(以 `#` 作前缀)用来定位到页面的对应位置,例如 `[props 大小写格式](/guide/components/props.html#prop-name-casing)`。 +链接中有时还会带有锚点(以 `#` 作前缀)用来定位到页面的对应位置,例如 `[props 大小写格式](/guide/components/props.html#prop-name-casing)`。 但是在 VitePress 中,由于锚点是对应 Markdown 内容中的 “标题行” 的,因此若改动了英文内容的标题行,别处引用此处的锚点就是失效了: diff --git a/src/api/application.md b/src/api/application.md index f992824df..424b882d5 100644 --- a/src/api/application.md +++ b/src/api/application.md @@ -155,12 +155,12 @@ /* ... */ }) - // 注册(对象形式的指令) + // 注册(对象形式的指令) app.directive('myDirective', { /* 自定义指令钩子 */ }) - // 注册(函数形式的指令) + // 注册(函数形式的指令) app.directive('myDirective', () => { /* ... */ }) diff --git a/src/api/composition-api-setup.md b/src/api/composition-api-setup.md index 634c20cf8..16ad3acca 100644 --- a/src/api/composition-api-setup.md +++ b/src/api/composition-api-setup.md @@ -86,16 +86,16 @@ export default { ```js export default { setup(props, context) { - // 透传 Attributes(非响应式的对象,等价于 $attrs) + // 透传 Attributes (非响应式的对象,等价于 $attrs) console.log(context.attrs) - // 插槽(非响应式的对象,等价于 $slots) + // 插槽(非响应式的对象,等价于 $slots) console.log(context.slots) - // 触发事件(函数,等价于 $emit) + // 触发事件(函数,等价于 $emit) console.log(context.emit) - // 暴露公共属性(函数) + // 暴露公共属性(函数) console.log(context.expose) } } diff --git a/src/api/options-lifecycle.md b/src/api/options-lifecycle.md index 8fde60a63..158884dc4 100644 --- a/src/api/options-lifecycle.md +++ b/src/api/options-lifecycle.md @@ -217,9 +217,9 @@ **错误捕获注意事项** - - 在使用异步 `setup()` 函数(使用了顶层 `await`)的组件中,即使 `setup()` 抛出了错误,Vue 也会尝试渲染组件模板。这可能会导致更多错误,因为在渲染组件模板时,可能会尝试访问失败的 `setup()` 上下文中不存在的属性。当捕获这类组件的错误时,应当同时准备好捕获异步 `setup()`(永远会先抛出错误)和失败的渲染过程中的错误。 + - 在使用异步 `setup()` 函数 (使用了顶层 `await`) 的组件中,即使 `setup()` 抛出了错误,Vue 也会尝试渲染组件模板。这可能会导致更多错误,因为在渲染组件模板时,可能会尝试访问失败的 `setup()` 上下文中不存在的属性。当捕获这类组件的错误时,应当同时准备好捕获异步 `setup()` (永远会先抛出错误) 和失败的渲染过程中的错误。 - - 在 `` 的父组件中替换出错的子组件会导致 SSR 的激活不匹配。相反,尽量将可能抛出错误的逻辑从子组件的 `setup()` 中抽成一个独立的函数并在父组件的 `setup()` 中执行,这样就可以安全地 `try/catch` 执行过程,并在渲染实际的子组件前根据需要进行替换。 + - 在 `` 的父组件中替换出错的子组件会导致 SSR 的激活不匹配。相反,尽量将可能抛出错误的逻辑从子组件的 `setup()` 中抽成一个独立的函数并在父组件的 `setup()` 中执行,这样就可以安全地 `try/catch` 执行过程,并在渲染实际的子组件前根据需要进行替换。 ## renderTracked {#rendertracked} diff --git a/src/guide/best-practices/performance.md b/src/guide/best-practices/performance.md index ddf106274..e9da9645e 100644 --- a/src/guide/best-practices/performance.md +++ b/src/guide/best-practices/performance.md @@ -84,7 +84,7 @@ import { defineAsyncComponent } from 'vue' // 会为 Foo.vue 及其依赖创建单独的一个块 // 它只会按需加载 -//(即该异步组件在页面中被渲染时) +// (即该异步组件在页面中被渲染时) const Foo = defineAsyncComponent(() => import('./Foo.vue')) ``` diff --git a/src/guide/best-practices/production-deployment.md b/src/guide/best-practices/production-deployment.md index 1ac9e773e..f6d63e00f 100644 --- a/src/guide/best-practices/production-deployment.md +++ b/src/guide/best-practices/production-deployment.md @@ -13,16 +13,16 @@ ## 不使用构建工具 {#without-build-tools} -如果你没有使用任何构建工具,而是从 CDN 或其他源来加载 Vue,请确保在部署时使用的是生产环境版本(以 `.prod.js` 结尾的构建文件)。生产环境版本会被最小化,并移除了所有仅用于开发环境的代码分支。 +如果你没有使用任何构建工具,而是从 CDN 或其他源来加载 Vue,请确保在部署时使用的是生产环境版本(以 `.prod.js` 结尾的构建文件)。生产环境版本会被最小化,并移除了所有仅用于开发环境的代码分支。 -- 如果需要使用全局变量版本(通过 `Vue` 全局变量访问):请使用 `vue.global.prod.js`。 -- 如果需要 ESM 版本(通过原生 ESM 导入访问):请使用 `vue.esm-browser.prod.js`。 +- 如果需要使用全局变量版本(通过 `Vue` 全局变量访问):请使用 `vue.global.prod.js`。 +- 如果需要 ESM 版本(通过原生 ESM 导入访问):请使用 `vue.esm-browser.prod.js`。 更多细节请参考[构建文件指南](https://github.com/vuejs/core/tree/main/packages/vue#which-dist-file-to-use)。 ## 使用构建工具 {#with-build-tools} -通过 `create-vue`(基于 Vite)或是 Vue CLI(基于 webpack)搭建的项目都已经预先做好了针对生产环境的配置。 +通过 `create-vue` (基于 Vite) 或是 Vue CLI (基于 webpack) 搭建的项目都已经预先做好了针对生产环境的配置。 如果使用了自定义的构建,请确保: diff --git a/src/guide/built-ins/suspense.md b/src/guide/built-ins/suspense.md index 8be0fc952..ababea920 100644 --- a/src/guide/built-ins/suspense.md +++ b/src/guide/built-ins/suspense.md @@ -18,10 +18,10 @@ outline: deep └─ ├─ - │ └─ (组件有异步的 setup()) + │ └─ (组件有异步的 setup()) └─ - ├─ (异步组件) - └─ (异步组件) + ├─ (异步组件) + └─ (异步组件) ``` 在这个组件树中有多个嵌套组件,要渲染出它们,首先得解析一些异步资源。如果没有 ``,则它们每个都需要处理自己的加载、报错和完成状态。在最坏的情况下,我们可能会在页面上看到三个旋转的加载态,在不同的时间显示出内容。 diff --git a/src/guide/components/props.md b/src/guide/components/props.md index 21ba21280..058c62efd 100644 --- a/src/guide/components/props.md +++ b/src/guide/components/props.md @@ -445,7 +445,7 @@ Vue 组件可以更细致地声明对传入的 props 的校验要求。比如我 ```js defineProps({ // 基础类型检查 - // (给出 `null` 和 `undefined` 值则会跳过任何类型检查) + // (给出 `null` 和 `undefined` 值则会跳过任何类型检查) propA: Number, // 多种可能的类型 propB: [String, Number], @@ -505,7 +505,7 @@ defineProps({ export default { props: { // 基础类型检查 - //(给出 `null` 和 `undefined` 值则会跳过任何类型检查) + // (给出 `null` 和 `undefined` 值则会跳过任何类型检查) propA: Number, // 多种可能的类型 propB: [String, Number], diff --git a/src/guide/essentials/template-refs.md b/src/guide/essentials/template-refs.md index 95aa0cf62..cea313014 100644 --- a/src/guide/essentials/template-refs.md +++ b/src/guide/essentials/template-refs.md @@ -104,7 +104,7 @@ watchEffect(() => { if (input.value) { input.value.focus() } else { - // 此时还未挂载,或此元素已经被卸载(例如通过 v-if 控制) + // 此时还未挂载,或此元素已经被卸载(例如通过 v-if 控制) } }) ``` diff --git a/src/guide/essentials/watchers.md b/src/guide/essentials/watchers.md index 5417c95bb..0f42bcf2e 100644 --- a/src/guide/essentials/watchers.md +++ b/src/guide/essentials/watchers.md @@ -346,7 +346,7 @@ watchEffect(async () => { }) ``` -这个例子中,回调会立即执行,不需要指定 `immediate: true`。在执行期间,它会自动追踪 `todoId.value` 作为依赖(和计算属性类似)。每当 `todoId.value` 变化时,回调会再次执行。有了 `watchEffect()`,我们不再需要明确传递 `todoId` 作为源值。 +这个例子中,回调会立即执行,不需要指定 `immediate: true`。在执行期间,它会自动追踪 `todoId.value` 作为依赖(和计算属性类似)。每当 `todoId.value` 变化时,回调会再次执行。有了 `watchEffect()`,我们不再需要明确传递 `todoId` 作为源值。 你可以参考一下[这个例子](/examples/#fetching-data)的 `watchEffect` 和响应式的数据请求的操作。 diff --git a/src/guide/extras/web-components.md b/src/guide/extras/web-components.md index 7c6940f4a..83bccace8 100644 --- a/src/guide/extras/web-components.md +++ b/src/guide/extras/web-components.md @@ -106,10 +106,10 @@ const MyVueElement = defineCustomElement({ customElements.define('my-vue-element', MyVueElement) // 你也可以编程式地实例化元素: -// (必须在注册之后) +// (必须在注册之后) document.body.appendChild( new MyVueElement({ - // 初始化 props(可选) + // 初始化 props (可选) }) ) ``` diff --git a/src/guide/scaling-up/ssr.md b/src/guide/scaling-up/ssr.md index 15c5e9f6f..dbb4df34f 100644 --- a/src/guide/scaling-up/ssr.md +++ b/src/guide/scaling-up/ssr.md @@ -268,7 +268,7 @@ Vite 提供了内置的 [Vue 服务端渲染支持](https://cn.vitejs.dev/guide/ 推荐的解决方案是在每个请求中为整个应用创建一个全新的实例,包括 router 和全局 store。然后,我们使用[应用层级的 provide 方法](/guide/components/provide-inject#app-level-provide)来提供共享状态,并将其注入到需要它的组件中,而不是直接在组件中将其导入: ```js -// app.js (在服务端和客户端间共享) +// app.js (在服务端和客户端间共享) import { createSSRApp } from 'vue' import { createStore } from './store.js' diff --git a/src/guide/scaling-up/testing.md b/src/guide/scaling-up/testing.md index 75f5dc168..0155921dd 100644 --- a/src/guide/scaling-up/testing.md +++ b/src/guide/scaling-up/testing.md @@ -55,7 +55,7 @@ import { VTCodeGroup, VTCodeGroupTab } from '@vue/theme' ## 单元测试 {#unit-testing} -编写单元测试是为了验证小的、独立的代码单元是否按预期工作。一个单元测试通常覆盖一个单个函数、类、组合式函数或模块。单元测试侧重于逻辑上的正确性,只关注应用整体功能的一小部分。他们可能会模拟你的应用环境的很大一部分(如初始状态、复杂的类、第三方模块和网络请求)。 +编写单元测试是为了验证小的、独立的代码单元是否按预期工作。一个单元测试通常覆盖一个单个函数、类、组合式函数或模块。单元测试侧重于逻辑上的正确性,只关注应用整体功能的一小部分。他们可能会模拟你的应用环境的很大一部分(如初始状态、复杂的类、第三方模块和网络请求)。 一般来说,单元测试将捕获函数的业务逻辑和逻辑正确性的问题。 @@ -114,7 +114,7 @@ describe('increment', () => { 1. 白盒:单元测试 - 白盒测试知晓一个组件的实现细节和依赖关系。它们更专注于将组件进行更 **独立** 的测试。这些测试通常会涉及到模拟一些组件的部分子组件,以及设置插件的状态和依赖性(例如 Pinia)。 + 白盒测试知晓一个组件的实现细节和依赖关系。它们更专注于将组件进行更 **独立** 的测试。这些测试通常会涉及到模拟一些组件的部分子组件,以及设置插件的状态和依赖性(例如 Pinia)。 2. 黑盒:组件测试 @@ -145,7 +145,7 @@ describe('increment', () => { - 对于 **视图** 的测试:根据输入 prop 和插槽断言渲染输出是否正确。 - 对于 **交互** 的测试:断言渲染的更新是否正确或触发的事件是否正确地响应了用户输入事件。 - 在下面的例子中,我们展示了一个步进器(Stepper)组件,它拥有一个标记为 `increment` 的可点击的 DOM 元素。我们还传入了一个名为 `max` 的 prop 防止步进器增长超过 `2`,因此如果我们点击了按钮 3 次,视图将仍然显示 `2`。 + 在下面的例子中,我们展示了一个步进器 (Stepper) 组件,它拥有一个标记为 `increment` 的可点击的 DOM 元素。我们还传入了一个名为 `max` 的 prop 防止步进器增长超过 `2`,因此如果我们点击了按钮 3 次,视图将仍然显示 `2`。 我们不了解这个步进器的实现细节,只知道“输入”是这个 `max` prop,“输出”是这个组件状态所呈现出的视图。 @@ -220,7 +220,7 @@ await fireEvent.click(button) - 不要去断言一个组件实例的私有状态或测试一个组件的私有方法。测试实现细节会使测试代码太脆弱,因为当实现发生变化时,它们更有可能失败并需要更新重写。 - 组件的最终工作是渲染正确的 DOM 输出,所以专注于 DOM 输出的测试提供了足够的正确性保证(如果你不需要更多其他方面测试的话),同时更加健壮、需要的改动更少。 + 组件的最终工作是渲染正确的 DOM 输出,所以专注于 DOM 输出的测试提供了足够的正确性保证(如果你不需要更多其他方面测试的话),同时更加健壮、需要的改动更少。 不要完全依赖快照测试。断言 HTML 字符串并不能完全说明正确性。应当编写有意图的测试。 @@ -232,7 +232,7 @@ await fireEvent.click(button) - [Cypress 组件测试](https://on.cypress.io/component) 会预期其准确地渲染样式或者触发原生 DOM 事件。它可以搭配 [@testing-library/cypress](https://testing-library.com/docs/cypress-testing-library/intro) 这个库一同进行测试。 -Vitest 和基于浏览器的运行器之间的主要区别是速度和执行上下文。简而言之,基于浏览器的运行器,如 Cypress,可以捕捉到基于 Node 的运行器(如 Vitest)所不能捕捉的问题(比如样式问题、原生 DOM 事件、Cookies、本地存储和网络故障),但基于浏览器的运行器比 Vitest *慢几个数量级*,因为它们要执行打开浏览器,编译样式表以及其他步骤。Cypress 是一个基于浏览器的运行器,支持组件测试。请阅读 [Vitest 文档的“比较”这一章](https://vitest.dev/guide/comparisons.html#cypress) 了解 Vitest 和 Cypress 最新的比较信息。 +Vitest 和基于浏览器的运行器之间的主要区别是速度和执行上下文。简而言之,基于浏览器的运行器,如 Cypress,可以捕捉到基于 Node 的运行器(如 Vitest) 所不能捕捉的问题(比如样式问题、原生 DOM 事件、Cookies、本地存储和网络故障),但基于浏览器的运行器比 Vitest *慢几个数量级*,因为它们要执行打开浏览器,编译样式表以及其他步骤。Cypress 是一个基于浏览器的运行器,支持组件测试。请阅读 [Vitest 文档的“比较”这一章](https://vitest.dev/guide/comparisons.html#cypress) 了解 Vitest 和 Cypress 最新的比较信息。 ### 组件挂载库 {#mounting-libraries} @@ -250,13 +250,13 @@ Vitest 和基于浏览器的运行器之间的主要区别是速度和执行上 - [WebdriverIO](https://webdriver.io/docs/component-testing/vue) 用于跨浏览器组件测试,该测试依赖于基于标准自动化的原生用户交互。它也可以与测试库一起使用。 -## 端到端(E2E)测试 {#e2e-testing} +## 端到端 (E2E) 测试 {#e2e-testing} 虽然单元测试为所写的代码提供了一定程度的验证,但单元测试和组件测试在部署到生产时,对应用整体覆盖的能力有限。因此,端到端测试针对的可以说是应用最重要的方面:当用户实际使用你的应用时发生了什么。 端到端测试的重点是多页面的应用表现,针对你的应用在生产环境下进行网络请求。他们通常需要建立一个数据库或其他形式的后端,甚至可能针对一个预备上线的环境运行。 -端到端测试通常会捕捉到路由、状态管理库、顶级组件(常见为 App 或 Layout)、公共资源或任何请求处理方面的问题。如上所述,它们可以捕捉到单元测试或组件测试无法捕捉的关键问题。 +端到端测试通常会捕捉到路由、状态管理库、顶级组件(常见为 App 或 Layout)、公共资源或任何请求处理方面的问题。如上所述,它们可以捕捉到单元测试或组件测试无法捕捉的关键问题。 端到端测试不导入任何 Vue 应用的代码,而是完全依靠在真实浏览器中浏览整个页面来测试你的应用。 @@ -276,7 +276,7 @@ Vitest 和基于浏览器的运行器之间的主要区别是速度和执行上 #### 更快的反馈 {#faster-feedback-loops} -端到端测试和相应开发过程的主要问题之一是,运行整个套件需要很长的时间。通常情况下,这只在持续集成和部署(CI/CD)管道中进行。现代的端到端测试框架通过增加并行化等功能来帮助解决这个问题,这使得 CI/CD 管道的运行速度比以前快了几倍。此外,在本地开发时,能够有选择地为你正在工作的页面运行单个测试,同时还提供测试的热重载,大大提高了开发者的工作流程和生产力。 +端到端测试和相应开发过程的主要问题之一是,运行整个套件需要很长的时间。通常情况下,这只在持续集成和部署 (CI/CD) 管道中进行。现代的端到端测试框架通过增加并行化等功能来帮助解决这个问题,这使得 CI/CD 管道的运行速度比以前快了几倍。此外,在本地开发时,能够有选择地为你正在工作的页面运行单个测试,同时还提供测试的热重载,大大提高了开发者的工作流程和生产力。 #### 第一优先级的调试体验 {#first-class-debugging-experience} @@ -284,7 +284,7 @@ Vitest 和基于浏览器的运行器之间的主要区别是速度和执行上 #### 无头模式下的可见性 {#visibility-in-headless-mode} -当端到端测试在 CI/CD 管道中运行时,它们通常在无头浏览器(即不带界面的浏览器)中运行。因此,当错误发生时,现代端到端测试框架的一个关键特性是能够在不同的测试阶段查看应用的快照、视频,从而深入了解错误的原因。而在很早以前,要手动维护这些集成是非常繁琐的。 +当端到端测试在 CI/CD 管道中运行时,它们通常在无头浏览器(即不带界面的浏览器)中运行。因此,当错误发生时,现代端到端测试框架的一个关键特性是能够在不同的测试阶段查看应用的快照、视频,从而深入了解错误的原因。而在很早以前,要手动维护这些集成是非常繁琐的。 ### 推荐方案 {#recommendation-2} @@ -330,7 +330,7 @@ export default defineConfig({ // 启用类似 jest 的全局测试 API globals: true, // 使用 happy-dom 模拟 DOM - // 这需要你安装 happy-dom 作为对等依赖(peer dependency) + // 这需要你安装 happy-dom 作为对等依赖 (peer dependency) environment: 'happy-dom' } })