diff --git a/.vitepress/config.js b/.vitepress/config.js
index 5f8ca76..8e337bc 100644
--- a/.vitepress/config.js
+++ b/.vitepress/config.js
@@ -1,156 +1,20 @@
+import locales from "./locales"
+
+/**
+ * @type {import('vitepress').UserConfig}
+ */
export default {
- title: 'Vue 3 Migration Guide',
- description: 'Guide on migrating from Vue 2 to Vue 3',
srcDir: 'src',
+ locales: locales.vitepressConfig,
+
themeConfig: {
- nav: [{ text: 'Vue 3 Docs', link: 'https://vuejs.org' }],
-
- sidebar: [
- {
- text: 'Guide',
- items: [
- { text: 'Overview', link: '/' },
- { text: 'New Recommendations', link: '/recommendations' },
- { text: 'Migration Build', link: '/migration-build' },
- {
- text: 'Breaking Changes',
- link: '/breaking-changes/'
- }
- ]
- },
- {
- text: 'Global API',
- items: [
- {
- text: 'Global API Application Instance',
- link: '/breaking-changes/global-api'
- },
- {
- text: 'Global API Treeshaking',
- link: '/breaking-changes/global-api-treeshaking'
- }
- ]
- },
- {
- text: 'Template Directives',
- items: [
- { text: 'v-model', link: '/breaking-changes/v-model' },
- {
- text: 'key Usage Change',
- link: '/breaking-changes/key-attribute'
- },
- {
- text: 'v-if vs. v-for Precedence',
- link: '/breaking-changes/v-if-v-for'
- },
- { text: 'v-bind Merge Behavior', link: '/breaking-changes/v-bind' },
- {
- text: 'v-on.native modifier removed',
- link: '/breaking-changes/v-on-native-modifier-removed'
- }
- ]
- },
- {
- text: 'Components',
- items: [
- {
- text: 'Functional Components',
- link: '/breaking-changes/functional-components'
- },
- {
- text: 'Async Components',
- link: '/breaking-changes/async-components'
- },
- { text: 'emits Option', link: '/breaking-changes/emits-option' }
- ]
- },
- {
- text: 'Render Function',
- items: [
- {
- text: 'Render Function API',
- link: '/breaking-changes/render-function-api'
- },
- {
- text: 'Slots Unification',
- link: '/breaking-changes/slots-unification'
- },
- {
- text: '$listeners merged into $attrs',
- link: '/breaking-changes/listeners-removed'
- },
- {
- text: '$attrs includes class & style',
- link: '/breaking-changes/attrs-includes-class-style'
- }
- ]
- },
- {
- text: 'Custom Elements',
- items: [
- {
- text: 'Custom Elements Interop Changes',
- link: '/breaking-changes/custom-elements-interop'
- }
- ]
- },
- {
- text: 'Removed APIs',
- items: [
- {
- text: 'v-on keyCode Modifiers',
- link: '/breaking-changes/keycode-modifiers'
- },
- { text: 'Events API', link: '/breaking-changes/events-api' },
- { text: 'Filters', link: '/breaking-changes/filters' },
- {
- text: 'inline-template',
- link: '/breaking-changes/inline-template-attribute'
- },
- { text: '$children', link: '/breaking-changes/children' },
- { text: 'propsData option', link: '/breaking-changes/props-data' }
- ]
- },
- {
- text: 'Other Minor Changes',
- items: [
- {
- text: 'Attribute Coercion Behavior',
- link: '/breaking-changes/attribute-coercion'
- },
- {
- text: 'Custom Directives',
- link: '/breaking-changes/custom-directives'
- },
- { text: 'Data Option', link: '/breaking-changes/data-option' },
- {
- text: 'Mount API changes',
- link: '/breaking-changes/mount-changes'
- },
- {
- text: 'Props Default Function this Access',
- link: '/breaking-changes/props-default-this'
- },
- {
- text: 'Transition Class Change',
- link: '/breaking-changes/transition'
- },
- {
- text: 'Transition as Root',
- link: '/breaking-changes/transition-as-root'
- },
- {
- text: 'Transition Group Root Element',
- link: '/breaking-changes/transition-group'
- },
- {
- text: 'VNode lifecycle events',
- link: '/breaking-changes/vnode-lifecycle-events'
- },
- { text: 'Watch on Arrays', link: '/breaking-changes/watch' }
- ]
- }
- ]
+ localeLinks: {
+ items: [
+ {text: 'English', link: '/'},
+ {text: '中文简体', link: '/zh/'}
+ ]
+ },
+ locales: locales.themeConfig
}
}
diff --git a/.vitepress/locales/en.js b/.vitepress/locales/en.js
new file mode 100644
index 0000000..9cab33e
--- /dev/null
+++ b/.vitepress/locales/en.js
@@ -0,0 +1,159 @@
+export default {
+ vitepressConfig: {
+ title: 'Vue 3 Migration Guide',
+ description: 'Guide on migrating from Vue 2 to Vue 3',
+ lang: 'en-US'
+ },
+ themeConfig: {
+ nav: [
+ { text: 'Vue 3 Docs', link: 'https://vuejs.org' },
+ ],
+
+ sidebar: [
+ {
+ text: 'Guide',
+ items: [
+ { text: 'Overview', link: '/' },
+ { text: 'New Recommendations', link: '/recommendations' },
+ { text: 'Migration Build', link: '/migration-build' },
+ {
+ text: 'Breaking Changes',
+ link: '/breaking-changes/'
+ }
+ ]
+ },
+ {
+ text: 'Global API',
+ items: [
+ {
+ text: 'Global API Application Instance',
+ link: '/breaking-changes/global-api'
+ },
+ {
+ text: 'Global API Treeshaking',
+ link: '/breaking-changes/global-api-treeshaking'
+ }
+ ]
+ },
+ {
+ text: 'Template Directives',
+ items: [
+ { text: 'v-model', link: '/breaking-changes/v-model' },
+ {
+ text: 'key Usage Change',
+ link: '/breaking-changes/key-attribute'
+ },
+ {
+ text: 'v-if vs. v-for Precedence',
+ link: '/breaking-changes/v-if-v-for'
+ },
+ { text: 'v-bind Merge Behavior', link: '/breaking-changes/v-bind' },
+ {
+ text: 'v-on.native modifier removed',
+ link: '/breaking-changes/v-on-native-modifier-removed'
+ }
+ ]
+ },
+ {
+ text: 'Components',
+ items: [
+ {
+ text: 'Functional Components',
+ link: '/breaking-changes/functional-components'
+ },
+ {
+ text: 'Async Components',
+ link: '/breaking-changes/async-components'
+ },
+ { text: 'emits Option', link: '/breaking-changes/emits-option' }
+ ]
+ },
+ {
+ text: 'Render Function',
+ items: [
+ {
+ text: 'Render Function API',
+ link: '/breaking-changes/render-function-api'
+ },
+ {
+ text: 'Slots Unification',
+ link: '/breaking-changes/slots-unification'
+ },
+ {
+ text: '$listeners merged into $attrs',
+ link: '/breaking-changes/listeners-removed'
+ },
+ {
+ text: '$attrs includes class & style',
+ link: '/breaking-changes/attrs-includes-class-style'
+ }
+ ]
+ },
+ {
+ text: 'Custom Elements',
+ items: [
+ {
+ text: 'Custom Elements Interop Changes',
+ link: '/breaking-changes/custom-elements-interop'
+ }
+ ]
+ },
+ {
+ text: 'Removed APIs',
+ items: [
+ {
+ text: 'v-on keyCode Modifiers',
+ link: '/breaking-changes/keycode-modifiers'
+ },
+ { text: 'Events API', link: '/breaking-changes/events-api' },
+ { text: 'Filters', link: '/breaking-changes/filters' },
+ {
+ text: 'inline-template',
+ link: '/breaking-changes/inline-template-attribute'
+ },
+ { text: '$children', link: '/breaking-changes/children' },
+ { text: 'propsData option', link: '/breaking-changes/props-data' }
+ ]
+ },
+ {
+ text: 'Other Minor Changes',
+ items: [
+ {
+ text: 'Attribute Coercion Behavior',
+ link: '/breaking-changes/attribute-coercion'
+ },
+ {
+ text: 'Custom Directives',
+ link: '/breaking-changes/custom-directives'
+ },
+ { text: 'Data Option', link: '/breaking-changes/data-option' },
+ {
+ text: 'Mount API changes',
+ link: '/breaking-changes/mount-changes'
+ },
+ {
+ text: 'Props Default Function this Access',
+ link: '/breaking-changes/props-default-this'
+ },
+ {
+ text: 'Transition Class Change',
+ link: '/breaking-changes/transition'
+ },
+ {
+ text: 'Transition as Root',
+ link: '/breaking-changes/transition-as-root'
+ },
+ {
+ text: 'Transition Group Root Element',
+ link: '/breaking-changes/transition-group'
+ },
+ {
+ text: 'VNode lifecycle events',
+ link: '/breaking-changes/vnode-lifecycle-events'
+ },
+ { text: 'Watch on Arrays', link: '/breaking-changes/watch' }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/.vitepress/locales/index.js b/.vitepress/locales/index.js
new file mode 100644
index 0000000..ff3ef3c
--- /dev/null
+++ b/.vitepress/locales/index.js
@@ -0,0 +1,13 @@
+import en from './en'
+import zh from './zh'
+
+export default {
+ vitepressConfig: {
+ '/': en.vitepressConfig,
+ '/zh/': zh.vitepressConfig
+ },
+ themeConfig: {
+ '/': en.themeConfig,
+ '/zh/': zh.themeConfig
+ }
+}
\ No newline at end of file
diff --git a/.vitepress/locales/zh.js b/.vitepress/locales/zh.js
new file mode 100644
index 0000000..c69adf0
--- /dev/null
+++ b/.vitepress/locales/zh.js
@@ -0,0 +1,165 @@
+
+export default {
+ vitepressConfig: {
+ title: 'Vue 3 迁移指南',
+ description: '从Vue 2迁移到Vue 3的指南',
+ lang: 'zh-CN',
+ base: '/zh/',
+ },
+ themeConfig: {
+ docFooter: {
+ prev: '上一页',
+ next: '下一页',
+ },
+ outlineTitle: '本页目录',
+ nav: [
+ { text: 'Vue 3 文档', link: 'https://cn.vuejs.org' },
+ ],
+ sidebar: [
+ {
+ text: '指南',
+ items: [
+ { text: '概览', link: '/zh/' },
+ { text: '新的推荐', link: '/zh/recommendations' },
+ { text: '迁移构建', link: '/zh/migration-build' },
+ {
+ text: '非兼容性改变',
+ link: '/zh/breaking-changes/'
+ }
+ ]
+ },
+ {
+ text: '全局 API',
+ items: [
+ {
+ text: '全局 API 应用实例',
+ link: '/zh/breaking-changes/global-api'
+ },
+ {
+ text: '全局 API Treeshaking',
+ link: '/zh/breaking-changes/global-api-treeshaking'
+ }
+ ]
+ },
+ {
+ text: '模板指令',
+ items: [
+ { text: 'v-model', link: '/zh/breaking-changes/v-model' },
+ {
+ text: 'key 使用改变',
+ link: '/zh/breaking-changes/key-attribute'
+ },
+ {
+ text: 'v-if 与 v-for 优先级',
+ link: '/zh/breaking-changes/v-if-v-for'
+ },
+ { text: 'v-bind 合并行为', link: '/zh/breaking-changes/v-bind' },
+ {
+ text: 'v-on.native 移除',
+ link: '/zh/breaking-changes/v-on-native-modifier-removed'
+ }
+ ]
+ },
+ {
+ text: '组件',
+ items: [
+ {
+ text: '函数式组件',
+ link: '/zh/breaking-changes/functional-components'
+ },
+ {
+ text: '异步组件',
+ link: '/zh/breaking-changes/async-components'
+ },
+ { text: 'emits 选项', link: '/zh/breaking-changes/emits-option' }
+ ]
+ },
+ {
+ text: '渲染函数',
+ items: [
+ {
+ text: '渲染函数 API',
+ link: '/zh/breaking-changes/render-function-api'
+ },
+ {
+ text: '插槽统一',
+ link: '/zh/breaking-changes/slots-unification'
+ },
+ {
+ text: '$listeners 合并到 $attrs',
+ link: '/zh/breaking-changes/listeners-removed'
+ },
+ {
+ text: '$attrs 包含 class & style',
+ link: '/zh/breaking-changes/attrs-includes-class-style'
+ }
+ ]
+ },
+ {
+ text: '自定义元素',
+ items: [
+ {
+ text: '与自定义标签的互操作性',
+ link: '/zh/breaking-changes/custom-elements-interop'
+ }
+ ]
+ },
+ {
+ text: '移除的 APIs',
+ items: [
+ {
+ text: '按键修饰符',
+ link: '/zh/breaking-changes/keycode-modifiers'
+ },
+ { text: '事件 API', link: '/zh/breaking-changes/events-api' },
+ { text: '过滤器', link: '/zh/breaking-changes/filters' },
+ {
+ text: '内联模板',
+ link: '/zh/breaking-changes/inline-template-attribute'
+ },
+ { text: '$children', link: '/zh/breaking-changes/children' },
+ { text: 'propsData 选项', link: '/zh/breaking-changes/props-data' }
+ ]
+ },
+ {
+ text: '其他一些小的变化',
+ items: [
+ {
+ text: 'Attribute 强制行为',
+ link: '/zh/breaking-changes/attribute-coercion'
+ },
+ {
+ text: '自定义指令',
+ link: '/zh/breaking-changes/custom-directives'
+ },
+ { text: 'Data 选项', link: '/zh/breaking-changes/data-option' },
+ {
+ text: 'Mount API 的改变',
+ link: '/zh/breaking-changes/mount-changes'
+ },
+ {
+ text: 'Props 的默认函数访问 this',
+ link: '/zh/breaking-changes/props-default-this'
+ },
+ {
+ text: 'Transition class 名更改 ',
+ link: '/zh/breaking-changes/transition'
+ },
+ {
+ text: 'Transition 作为根节点',
+ link: '/zh/breaking-changes/transition-as-root'
+ },
+ {
+ text: 'TransitionGroup 根元素',
+ link: '/zh/breaking-changes/transition-group'
+ },
+ {
+ text: 'VNode 生命周期事件',
+ link: '/zh/breaking-changes/vnode-lifecycle-events'
+ },
+ { text: 'Watch 侦听数组', link: '/zh/breaking-changes/watch' }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/.vitepress/theme/MigrationBadges.vue b/.vitepress/theme/MigrationBadges.vue
index 2d5ce2a..46b1170 100644
--- a/.vitepress/theme/MigrationBadges.vue
+++ b/.vitepress/theme/MigrationBadges.vue
@@ -1,10 +1,20 @@
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1ac84bd..caa3be4 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1,4 +1,4 @@
-lockfileVersion: 5.4
+lockfileVersion: 5.3
specifiers:
vitepress: ^1.0.0-alpha.8
diff --git a/src/zh/breaking-changes/array-refs.md b/src/zh/breaking-changes/array-refs.md
new file mode 100644
index 0000000..43f26ff
--- /dev/null
+++ b/src/zh/breaking-changes/array-refs.md
@@ -0,0 +1,79 @@
+---
+title: v-for 中的 Ref 数组
+badges:
+ - breaking
+---
+
+# {{ $frontmatter.title }}
+
+在 Vue 2 中,在 `v-for` 中使用的 `ref` attribute 会用 ref 数组填充相应的 `$refs` property。当存在嵌套的 `v-for` 时,这种行为会变得不明确且效率低下。
+
+在 Vue 3 中,此类用法将不再自动创建 `$ref` 数组。要从单个绑定获取多个 ref,请将 `ref` 绑定到一个更灵活的函数上 (这是一个新特性):
+
+```html
+
+```
+
+结合选项式 API:
+
+```js
+export default {
+ data() {
+ return {
+ itemRefs: []
+ }
+ },
+ methods: {
+ setItemRef(el) {
+ if (el) {
+ this.itemRefs.push(el)
+ }
+ }
+ },
+ beforeUpdate() {
+ this.itemRefs = []
+ },
+ updated() {
+ console.log(this.itemRefs)
+ }
+}
+```
+
+结合组合式 API:
+
+```js
+import { onBeforeUpdate, onUpdated } from 'vue'
+
+export default {
+ setup() {
+ let itemRefs = []
+ const setItemRef = el => {
+ if (el) {
+ itemRefs.push(el)
+ }
+ }
+ onBeforeUpdate(() => {
+ itemRefs = []
+ })
+ onUpdated(() => {
+ console.log(itemRefs)
+ })
+ return {
+ setItemRef
+ }
+ }
+}
+```
+
+注意:
+
+- `itemRefs` 不必是数组:它也可以是一个对象,其 ref 可以通过迭代的 key 被设置。
+
+- 如有需要,`itemRefs` 也可以是响应式的,且可以被侦听。
+
+## 迁移策略
+
+[迁移构建开关:](migration-build.html#兼容性配置)
+
+- `V_FOR_REF`
+- `COMPILER_V_FOR_REF`
diff --git a/src/zh/breaking-changes/async-components.md b/src/zh/breaking-changes/async-components.md
new file mode 100644
index 0000000..79bacfe
--- /dev/null
+++ b/src/zh/breaking-changes/async-components.md
@@ -0,0 +1,98 @@
+---
+badges:
+ - new
+---
+
+# 异步组件
+
+## 概览
+
+以下是对变化的总体概述:
+
+- 新的 `defineAsyncComponent` 助手方法,用于显式地定义异步组件
+- `component` 选项被重命名为 `loader`
+- Loader 函数本身不再接收 `resolve` 和 `reject` 参数,且必须返回一个 Promise
+
+如需更深入的解释,请继续阅读!
+
+## 介绍
+
+以前,异步组件是通过将组件定义为返回 Promise 的函数来创建的,例如:
+
+```js
+const asyncModal = () => import('./Modal.vue')
+```
+
+或者,对于带有选项的更高阶的组件语法:
+
+```js
+const asyncModal = {
+ component: () => import('./Modal.vue'),
+ delay: 200,
+ timeout: 3000,
+ error: ErrorComponent,
+ loading: LoadingComponent
+}
+```
+
+## 3.x 语法
+
+现在,在 Vue 3 中,由于函数式组件被定义为纯函数,因此异步组件需要通过将其包裹在新的 `defineAsyncComponent` 助手方法中来显式地定义:
+
+```js
+import { defineAsyncComponent } from 'vue'
+import ErrorComponent from './components/ErrorComponent.vue'
+import LoadingComponent from './components/LoadingComponent.vue'
+
+// 不带选项的异步组件
+const asyncModal = defineAsyncComponent(() => import('./Modal.vue'))
+
+// 带选项的异步组件
+const asyncModalWithOptions = defineAsyncComponent({
+ loader: () => import('./Modal.vue'),
+ delay: 200,
+ timeout: 3000,
+ errorComponent: ErrorComponent,
+ loadingComponent: LoadingComponent
+})
+```
+
+::: tip 注意
+Vue Router 支持一个类似的机制来异步加载路由组件,也就是俗称的*懒加载*。尽管类似,但是这个功能和 Vue 所支持的异步组件是不同的。当用 Vue Router 配置路由组件时,你**不**应该使用 `defineAsyncComponent`。你可以在 Vue Router 文档的[懒加载路由](https://router.vuejs.org/zh/guide/advanced/lazy-loading.html)章节阅读更多相关内容。
+:::
+
+对 2.x 所做的另一个更改是,`component` 选项现在被重命名为 `loader`,以明确组件定义不能直接被提供。
+
+```js{4}
+import { defineAsyncComponent } from 'vue'
+
+const asyncModalWithOptions = defineAsyncComponent({
+ loader: () => import('./Modal.vue'),
+ delay: 200,
+ timeout: 3000,
+ errorComponent: ErrorComponent,
+ loadingComponent: LoadingComponent
+})
+```
+
+此外,与 2.x 不同,loader 函数不再接收 `resolve` 和 `reject` 参数,且必须始终返回 Promise。
+
+```js
+// 2.x 版本
+const oldAsyncComponent = (resolve, reject) => {
+ /* ... */
+}
+
+// 3.x 版本
+const asyncComponent = defineAsyncComponent(
+ () =>
+ new Promise((resolve, reject) => {
+ /* ... */
+ })
+)
+```
+
+有关异步组件用法的详细信息,请参阅:
+
+- [指南:异步组件](https://cn.vuejs.org/guide/components/async.html)
+- [迁移构建开关:`COMPONENT_ASYNC`](../migration-build.html#兼容性配置)
diff --git a/src/zh/breaking-changes/attribute-coercion.md b/src/zh/breaking-changes/attribute-coercion.md
new file mode 100644
index 0000000..687bbc0
--- /dev/null
+++ b/src/zh/breaking-changes/attribute-coercion.md
@@ -0,0 +1,146 @@
+---
+badges:
+ - breaking
+---
+
+# attribute 强制行为
+
+:::info 信息
+这是一个底层的内部 API 更改,绝大多数开发人员不会受到影响。
+:::
+
+## 概览
+
+以下是对变化的总体概述:
+
+- 移除枚举 attribute 的内部概念,并将这些 attribute 视为普通的非布尔 attribute
+- **非兼容**:如果值为布尔值 `false`,则不再移除 attribute。取而代之的是,它将被设置为 attr="false"。若要移除 attribute,应该使用 `null` 或者 `undefined`。
+
+如需更深入的解释,请继续阅读!
+
+## 2.x 语法
+
+在 2.x,我们有以下策略来强制 `v-bind` 的值:
+
+- 对于某些 attribute/元素对,Vue 始终使用相应的 IDL attribute (property):[比如 ``,`