From 794629c666535ba1454ba1adebedf9c25248799c Mon Sep 17 00:00:00 2001 From: Serhii Matrunchyk <2089828+matrunchyk@users.noreply.github.com> Date: Mon, 1 May 2023 17:39:53 +0300 Subject: [PATCH] feat: Ukrainian language (#48) * feat: Ukrainian language * feat: Migration build * feat: Recommendations * feat: Links, breaking changes page * feat: global api * fix: #9 * fix: #10 v-model * #21 translate attr imcludes class and style * #20 Translate: listeners are removed * Update src/uk/breaking-changes/listeners-removed.md * Update src/uk/breaking-changes/listeners-removed.md * Update src/uk/breaking-changes/listeners-removed.md * Update src/uk/breaking-changes/listeners-removed.md * #19 Translate: Slots unification * #18 Translate: render function API * #28 Translate: PropsData * #27 Translate: * #27 Translate: * #26 Translate: inline-template attribute * #25 Translate: filters * Update src/uk/breaking-changes/filters.md * #24 Translate: events API * #23 Translate: keycode modifiers * Update src/uk/breaking-changes/keycode-modifiers.md * Translate: custom elements interop * Translate: custom directives #30 * Update src/uk/breaking-changes/custom-directives.md Co-authored-by: Nazar Niphone <74293442+nazar1ua@users.noreply.github.com> * Update src/uk/breaking-changes/custom-directives.md Co-authored-by: Nazar Niphone <74293442+nazar1ua@users.noreply.github.com> * Update src/uk/breaking-changes/custom-directives.md Co-authored-by: Nazar Niphone <74293442+nazar1ua@users.noreply.github.com> * Update src/uk/breaking-changes/custom-directives.md Co-authored-by: Nazar Niphone <74293442+nazar1ua@users.noreply.github.com> * translation improvements * translate: key Attribute #11 * translate: v-bind merge behavior #13 * translate: v-if vs. v-for precedence #12 * translate: v-on.native modifier removed #14 * translate: title fix #14 * translate: functional components #15 * translate: async components #16 * translate: emits option #17 * translate: attribute coercion behavior #29 * translate: mount changes #32 * translate: props default this access #33 * translate: transition class change #34 * translate: transition as root #35 * translate: transition group root element #36 * translate: vnode lifecycle events #37 * translate: watch on arrays #38 * Update src/uk/breaking-changes/v-if-v-for.md Co-authored-by: Olesya Kogivchak * Update src/uk/breaking-changes/v-if-v-for.md Co-authored-by: Olesya Kogivchak * Update src/uk/breaking-changes/key-attribute.md Co-authored-by: Olesya Kogivchak * Translate: data option --------- Co-authored-by: olesyakogivchak Co-authored-by: Nazar Niphone <74293442+nazar1ua@users.noreply.github.com> Co-authored-by: Max Druzhinin <6406412+maxdzin@users.noreply.github.com> Co-authored-by: Olesya Kogivchak --- .gitignore | 1 + .vitepress/config.js | 1 + .vitepress/locales/index.js | 3 + .vitepress/locales/uk.js | 164 +++++++++ .vitepress/theme/MigrationBadges.vue | 6 + src/uk/VueMastery.vue | 95 +++++ src/uk/breaking-changes/async-components.md | 98 +++++ src/uk/breaking-changes/attribute-coercion.md | 144 ++++++++ .../attrs-includes-class-style.md | 71 ++++ src/uk/breaking-changes/children.md | 44 +++ src/uk/breaking-changes/custom-directives.md | 111 ++++++ .../custom-elements-interop.md | 134 +++++++ src/uk/breaking-changes/data-option.md | 128 +++++++ src/uk/breaking-changes/emits-option.md | 97 +++++ src/uk/breaking-changes/events-api.md | 104 ++++++ src/uk/breaking-changes/filters.md | 107 ++++++ .../breaking-changes/functional-components.md | 120 ++++++ .../global-api-treeshaking.md | 166 +++++++++ src/uk/breaking-changes/global-api.md | 291 +++++++++++++++ src/uk/breaking-changes/index.md | 67 ++++ .../inline-template-attribute.md | 84 +++++ src/uk/breaking-changes/key-attribute.md | 91 +++++ src/uk/breaking-changes/keycode-modifiers.md | 72 ++++ src/uk/breaking-changes/listeners-removed.md | 76 ++++ src/uk/breaking-changes/mount-changes.md | 98 +++++ src/uk/breaking-changes/props-data.md | 41 +++ src/uk/breaking-changes/props-default-this.md | 37 ++ .../breaking-changes/render-function-api.md | 146 ++++++++ src/uk/breaking-changes/slots-unification.md | 68 ++++ src/uk/breaking-changes/transition-as-root.md | 61 ++++ src/uk/breaking-changes/transition-group.md | 45 +++ src/uk/breaking-changes/transition.md | 67 ++++ src/uk/breaking-changes/v-bind.md | 48 +++ src/uk/breaking-changes/v-if-v-for.md | 36 ++ src/uk/breaking-changes/v-model.md | 196 ++++++++++ .../v-on-native-modifier-removed.md | 59 +++ .../vnode-lifecycle-events.md | 42 +++ src/uk/breaking-changes/watch.md | 32 ++ src/uk/index.md | 49 +++ src/uk/migration-build.md | 343 ++++++++++++++++++ src/uk/new/fragments.md | 40 ++ src/uk/recommendations.md | 75 ++++ 42 files changed, 3758 insertions(+) create mode 100644 .vitepress/locales/uk.js create mode 100644 src/uk/VueMastery.vue create mode 100644 src/uk/breaking-changes/async-components.md create mode 100644 src/uk/breaking-changes/attribute-coercion.md create mode 100644 src/uk/breaking-changes/attrs-includes-class-style.md create mode 100644 src/uk/breaking-changes/children.md create mode 100644 src/uk/breaking-changes/custom-directives.md create mode 100644 src/uk/breaking-changes/custom-elements-interop.md create mode 100644 src/uk/breaking-changes/data-option.md create mode 100644 src/uk/breaking-changes/emits-option.md create mode 100644 src/uk/breaking-changes/events-api.md create mode 100644 src/uk/breaking-changes/filters.md create mode 100644 src/uk/breaking-changes/functional-components.md create mode 100644 src/uk/breaking-changes/global-api-treeshaking.md create mode 100644 src/uk/breaking-changes/global-api.md create mode 100644 src/uk/breaking-changes/index.md create mode 100644 src/uk/breaking-changes/inline-template-attribute.md create mode 100644 src/uk/breaking-changes/key-attribute.md create mode 100644 src/uk/breaking-changes/keycode-modifiers.md create mode 100644 src/uk/breaking-changes/listeners-removed.md create mode 100644 src/uk/breaking-changes/mount-changes.md create mode 100644 src/uk/breaking-changes/props-data.md create mode 100644 src/uk/breaking-changes/props-default-this.md create mode 100644 src/uk/breaking-changes/render-function-api.md create mode 100644 src/uk/breaking-changes/slots-unification.md create mode 100644 src/uk/breaking-changes/transition-as-root.md create mode 100644 src/uk/breaking-changes/transition-group.md create mode 100644 src/uk/breaking-changes/transition.md create mode 100644 src/uk/breaking-changes/v-bind.md create mode 100644 src/uk/breaking-changes/v-if-v-for.md create mode 100644 src/uk/breaking-changes/v-model.md create mode 100644 src/uk/breaking-changes/v-on-native-modifier-removed.md create mode 100644 src/uk/breaking-changes/vnode-lifecycle-events.md create mode 100644 src/uk/breaking-changes/watch.md create mode 100644 src/uk/index.md create mode 100644 src/uk/migration-build.md create mode 100644 src/uk/new/fragments.md create mode 100644 src/uk/recommendations.md diff --git a/.gitignore b/.gitignore index 0cdb973..3a6b17d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ node_modules .DS_Store .pnpm-debug.log .vitepress/dist +.idea diff --git a/.vitepress/config.js b/.vitepress/config.js index cbb921e..f705e0d 100644 --- a/.vitepress/config.js +++ b/.vitepress/config.js @@ -14,6 +14,7 @@ export default { {text: 'English', link: '/'}, {text: '中文简体', link: '/zh/'}, {text: '日本語(翻訳中)', link: '/ja/'}, + {text: 'Українська', link: '/uk/'}, ] }, locales: locales.themeConfig diff --git a/.vitepress/locales/index.js b/.vitepress/locales/index.js index bdd2f4b..cdc5ec6 100644 --- a/.vitepress/locales/index.js +++ b/.vitepress/locales/index.js @@ -1,16 +1,19 @@ import en from './en' import zh from './zh' import ja from './ja' +import uk from './uk' export default { vitepressConfig: { '/': en.vitepressConfig, '/zh/': zh.vitepressConfig, '/ja/': ja.vitepressConfig, + '/uk/': uk.vitepressConfig, }, themeConfig: { '/': en.themeConfig, '/zh/': zh.themeConfig, '/ja/': ja.themeConfig, + '/uk/': uk.themeConfig, } } diff --git a/.vitepress/locales/uk.js b/.vitepress/locales/uk.js new file mode 100644 index 0000000..18ca7b0 --- /dev/null +++ b/.vitepress/locales/uk.js @@ -0,0 +1,164 @@ +export default { + vitepressConfig: { + title: 'Міграція з Vue 3', + description: 'Гід з міграції з Vue 2 на Vue 3', + lang: 'ua-UK' + }, + themeConfig: { + docFooter: { + prev: 'Попередня сторінка', + next: 'Наступна сторінка', + }, + outlineTitle: 'На цій сторінці', + nav: [ + { text: 'Документація по Vue 3', link: 'https://ua.vuejs.org' }, + ], + + sidebar: [ + { + text: 'Гід', + items: [ + { text: 'Огляд', link: '/uk/' }, + { text: 'Нові рекомендації', link: '/uk/recommendations' }, + { text: 'Міграційна збірка', link: '/uk/migration-build' }, + { + text: 'Несумісні зміни', + link: '/uk/breaking-changes/' + } + ] + }, + { + text: 'Глобальний API', + items: [ + { + text: 'Екземпляр програми глобального API', + link: '/uk/breaking-changes/global-api' + }, + { + text: 'Глобальний API струшування дерева', + link: '/uk/breaking-changes/global-api-treeshaking' + } + ] + }, + { + text: 'Шаблон директив', + items: [ + { text: 'v-model', link: '/uk/breaking-changes/v-model' }, + { + text: 'Зміни використання key', + link: '/uk/breaking-changes/key-attribute' + }, + { + text: 'Пріоритет v-if проти v-for', + link: '/uk/breaking-changes/v-if-v-for' + }, + { text: 'Поведінка злиття v-bind', link: '/uk/breaking-changes/v-bind' }, + { + text: 'Модифікатор v-on.native видалено', + link: '/uk/breaking-changes/v-on-native-modifier-removed' + } + ] + }, + { + text: 'Компоненти', + items: [ + { + text: 'Функціональні компоненти', + link: '/uk/breaking-changes/functional-components' + }, + { + text: 'Асинхронні компоненти', + link: '/uk/breaking-changes/async-components' + }, + { text: 'Опція emits', link: '/uk/breaking-changes/emits-option' } + ] + }, + { + text: 'Функції рендерингу', + items: [ + { + text: 'API функцій рендерингу', + link: '/uk/breaking-changes/render-function-api' + }, + { + text: 'Уніфікація слотів', + link: '/uk/breaking-changes/slots-unification' + }, + { + text: '$listeners об\'єднано з $attrs', + link: '/uk/breaking-changes/listeners-removed' + }, + { + text: '$attrs включає class & style', + link: '/uk/breaking-changes/attrs-includes-class-style' + } + ] + }, + { + text: 'Спеціальні елементи', + items: [ + { + text: 'Зміни взаємодії', + link: '/uk/breaking-changes/custom-elements-interop' + } + ] + }, + { + text: 'Видалені API', + items: [ + { + text: 'Модифікатор v-on keyCode', + link: '/uk/breaking-changes/keycode-modifiers' + }, + { text: 'API подій', link: '/uk/breaking-changes/events-api' }, + { text: 'Фільтри', link: '/uk/breaking-changes/filters' }, + { + text: 'inline-template', + link: '/uk/breaking-changes/inline-template-attribute' + }, + { text: '$children', link: '/uk/breaking-changes/children' }, + { text: 'Опція propsData', link: '/uk/breaking-changes/props-data' } + ] + }, + { + text: 'Інші незначні зміни', + items: [ + { + text: 'Поведінка приведення атрибутів', + link: '/uk/breaking-changes/attribute-coercion' + }, + { + text: 'Користувацькі директиви', + link: '/uk/breaking-changes/custom-directives' + }, + { text: 'Опція Data', link: '/uk/breaking-changes/data-option' }, + { + text: 'Зміни в API монтування', + link: '/uk/breaking-changes/mount-changes' + }, + { + text: 'Доступ до this в функції реквізитів', + link: '/uk/breaking-changes/props-default-this' + }, + { + text: 'Зміни класів переходів', + link: '/uk/breaking-changes/transition' + }, + { + text: 'Transition як кореневий елемент', + link: '/uk/breaking-changes/transition-as-root' + }, + { + text: 'Transition Group як кореневий елемент', + link: '/uk/breaking-changes/transition-group' + }, + { + text: 'Події життєвого циклу VNode', + link: '/uk/breaking-changes/vnode-lifecycle-events' + }, + { text: 'Спостерігачі за масивами', link: '/uk/breaking-changes/watch' } + ] + } + ] + } +} diff --git a/.vitepress/theme/MigrationBadges.vue b/.vitepress/theme/MigrationBadges.vue index 81ae1f5..48a0833 100644 --- a/.vitepress/theme/MigrationBadges.vue +++ b/.vitepress/theme/MigrationBadges.vue @@ -19,6 +19,12 @@ const localeBadges = { breaking: '破壊的変更', removed: '削除', updated: '更新' + }, + 'ua-UK': { + new: 'нове', + breaking: 'несумісно', + removed: 'видалено', + updated: 'змінено' } } diff --git a/src/uk/VueMastery.vue b/src/uk/VueMastery.vue new file mode 100644 index 0000000..fa67c05 --- /dev/null +++ b/src/uk/VueMastery.vue @@ -0,0 +1,95 @@ + + + diff --git a/src/uk/breaking-changes/async-components.md b/src/uk/breaking-changes/async-components.md new file mode 100644 index 0000000..ffa84b2 --- /dev/null +++ b/src/uk/breaking-changes/async-components.md @@ -0,0 +1,98 @@ +--- +badges: + - new +--- + +# Асинхронні компоненти + +## Огляд + +Ось короткий огляд того, що змінилося: + +- Новий допоміжний метод `defineAsyncComponent`, який явно визначає асинхронні компоненти +- Опцію `component` перейменовано на `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 асинхронних компонентів. Вам **не** слід використовувати `defineAsyncComponent` під час налаштування компонентів маршруту за допомогою Vue Router. Ви можете прочитати більше про це в розділі [Маршрути відкладеного завантаження](https://router.vuejs.org/guide/advanced/lazy-loading.html) документації Vue Router. +::: + +Ще одна зміна, яка була зроблена порівняно з 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, функція завантажувача більше не отримує аргументи `resolve` і `reject` і має завжди повертати Promise. + +```js +// Версія 2.x +const oldAsyncComponent = (resolve, reject) => { + /* ... */ +} + +// Версія 3.x +const asyncComponent = defineAsyncComponent( + () => + new Promise((resolve, reject) => { + /* ... */ + }) +) +``` + +Додаткову інформацію про використання асинхронних компонентів дивіться тут: + +- [Посібник: Асинхронні компоненти](https://vuejs.org/guide/components/async.html) +- [Прапор збірки міграції: `COMPONENT_ASYNC`](../migration-build.html#compat-configuration) diff --git a/src/uk/breaking-changes/attribute-coercion.md b/src/uk/breaking-changes/attribute-coercion.md new file mode 100644 index 0000000..9f1b12e --- /dev/null +++ b/src/uk/breaking-changes/attribute-coercion.md @@ -0,0 +1,144 @@ +--- +badges: + - breaking +--- + +# Поведінка приведення атрибутів + +::: info Інформація +Це низькорівнева внутрішня зміна API, яка не впливає на більшість розробників. +::: + +## Огляд + +Ось короткий підсумок змін: + +- Відмова від внутрішньої концепції перерахованих атрибутів і обробка цих атрибутів так само, як і звичайних не булевих атрибутів +- **НЕСУМІСНО**: більше не видаляється атрибут, якщо його значенням є логічне значення `false`. Замість цього він встановлюється як attr="false". Щоб видалити атрибут, використовуйте `null` або `undefined`. + +Щоб дізнатися більше, читайте далі! + +## Синтаксис 2.x + +У версії 2.x, у нас були наступні стратегії для приведення значень `v-bind`: + +- Для деяких пар атрибут/елемент Vue завжди використовує відповідний IDL атрибут (властивість): [наприклад, `value` для ``, ` + +``` + +## 3.x Поведінка + +`$attrs` містить _усі_ атрибути, що полегшує їх застосування до іншого елемента. Наведений вище приклад тепер генерує наступний HTML: + +```html + +``` + +## Стратегія міграції + +Переконайтеся, що у компонентах, які використовують `inheritAttrs: false`, стилі все ще працюють належним чином. Якщо ви раніше покладалися на спеціальну поведінку `class` та `style`, то деякі візуальні ефекти можуть бути втрачені, оскільки ці атрибути тепер можуть бути застосовані до іншого елемента. + +[Прапор міграції збірки: `INSTANCE_ATTRS_CLASS_STYLE`](../migration-build.html#compat-configuration) + +## Дивіться також + +- [Відповідний RFC](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0031-attr-fallthrough.md) +- [Гід з міграції - видалено `$listeners`](./listeners-removed.md) +- [Гід з міграції - нова опція випромінювань](./emits-option.md) +- [Гід з міграції - видалено модифікатор `.native`](./v-on-native-modifier-removed.md) +- [Гід з міграції - зміни в API функцій рендерингу](./render-function-api.md) diff --git a/src/uk/breaking-changes/children.md b/src/uk/breaking-changes/children.md new file mode 100644 index 0000000..6425817 --- /dev/null +++ b/src/uk/breaking-changes/children.md @@ -0,0 +1,44 @@ +--- +badges: + - removed +--- + +# $children + +## Огляд + +Властивість екземпляра `$children` було видалено з Vue 3.0 і більше не підтримується. + +## 2.x Синтаксис + +У версії 2.x розробники могли отримати доступ до дочірніх компонентів поточного екземпляра за допомогою `this.$children`: + +```vue + + + +``` + +## 3.x Оновлення + +У версії 3.x властивість `$children` видалено і вона більше не підтримується. Замість цього, якщо вам потрібно отримати доступ до екземпляра дочірнього компонента, ми рекомендуємо використовувати референції шаблону. + +## Стратегія міграції + +[Прапор збірки міграції: `INSTANCE_CHILDREN`](../migration-build.html#compat-configuration) diff --git a/src/uk/breaking-changes/custom-directives.md b/src/uk/breaking-changes/custom-directives.md new file mode 100644 index 0000000..2e1351b --- /dev/null +++ b/src/uk/breaking-changes/custom-directives.md @@ -0,0 +1,111 @@ +--- +badges: + - breaking +--- + +# Користувацькі директиви + +## Огляд + +Функції хуків для директив було перейменовано для кращої відповідності життєвому циклу компонента. + +Крім того, рядок `expression` більше не передається як частина об'єкта `binding`. + +## 2.x Синтаксис + +У версії Vue 2 користувацькі директиви були створені за допомогою наведених нижче хуків для керування життєвим циклом елемента, кожен з яких є необов'язковим: + +- **bind** - Викликається, коли директива прив'язується до елемента, лише один раз. +- **inserted** - Викликається, коли елемент вставлено в батьківський DOM. +- **update** - Цей хук викликається, коли елемент оновлюється, але дочірні елементи ще не оновлено. +- **componentUpdated** - Цей хук викликається, коли елемент та його дочірні елементи оновилися. +- **unbind** - Цей хук викликається після видалення директиви. Також викликається тільки один раз. + +Ось один із прикладів: + +```html +

Виділіть цей текст яскраво-жовтим кольором

+``` + +```js +Vue.directive('highlight', { + bind(el, binding, vnode) { + el.style.background = binding.value + } +}) +``` + +Тут, під час початкових налаштувань для цього елемента, директива прив'язує стиль, передаючи через `value`, яке може бути оновлено до різних значень через застосунок. + +## 3.x Синтаксис + +Однак у версії Vue 3 ми створили більш цілісний API для користувацьких директив. Як ви можете бачити, вони значно відрізняються від методів життєвого циклу компонентів, хоча ми підключаємося до схожих подій. Тепер ми об'єднали їх ось так: + +- **created** - нове! Викликається перед застосуванням атрибутів елемента або слухачів подій. +- bind → **beforeMount** +- inserted → **mounted** +- **beforeUpdate**: нове! Він викликається перед оновленням самого елемента, так само як і хуки життєвого циклу компонента. +- update → видалено! Занадто багато подібностей до `updated`, тому це є зайвим. Будь ласка, використовуйте `updated`. +- componentUpdated → **updated** +- **beforeUnmount**: нове! Подібно до хуків життєвого циклу компонента, цей метод буде викликано безпосередньо перед тим, як елемент буде демонтовано. +- unbind -> **unmounted** + +Остаточний варіант API виглядає наступним чином: + +```js +const MyDirective = { + created(el, binding, vnode, prevVnode) {}, // нове + beforeMount() {}, + mounted() {}, + beforeUpdate() {}, // нове + updated() {}, + beforeUnmount() {}, // нове + unmounted() {} +} +``` + +Оновлений API можна використовувати так, як показано в попередньому прикладі: + +```html +

Виділіть цей текст яскраво-жовтим кольором

+``` + +```js +const app = Vue.createApp({}) + +app.directive('highlight', { + beforeMount(el, binding, vnode) { + el.style.background = binding.value + } +}) +``` + +Тепер, коли хуки життєвого циклу користувацьких директив дублюють життєвий цикл самих компонентів, про них стало легше думати та запам'ятовувати! + +### Крайній випадок: Доступ до екземпляра компонента + +Загалом рекомендується тримати директиви незалежними від екземпляра компонента, в якому вони використовуються. Доступ до екземпляра з користувацької директиви часто є ознакою того, що директива має бути компонентом. Однак існують ситуації, коли це дійсно має сенс. + +У версії Vue 2 доступ до екземпляра компонента здійснювався через аргумент `vnode`: + +```js +bind(el, binding, vnode) { + const vm = vnode.context +} +``` + +У версії Vue 3 екземпляр тепер є частиною `binding`: + +```js +mounted(el, binding, vnode) { + const vm = binding.instance +} +``` + +:::warning ЗАСТЕРЕЖЕННЯ +Завдяки підтримці [фрагментів](../new/fragments.html#overview) компоненти потенційно можуть мати більше одного кореневого вузла. При застосуванні до багатокореневого компонента користувацькі директиви буде проігноровано з виведенням попередження. +::: + +## Стратегія міграції + +[Прапорець збірки міграції: `CUSTOM_DIR`](../migration-build.html#compat-configuration) diff --git a/src/uk/breaking-changes/custom-elements-interop.md b/src/uk/breaking-changes/custom-elements-interop.md new file mode 100644 index 0000000..912891d --- /dev/null +++ b/src/uk/breaking-changes/custom-elements-interop.md @@ -0,0 +1,134 @@ +--- +badges: + - breaking +--- + +# Зміни у взаємодії користувацьких елементів + +## Огляд + +- **НЕСУМІСНО:** Перевірка того, чи слід розглядати теги як користувацькі елементи, тепер виконується під час компіляції шаблону, і її слід налаштовувати за допомогою опцій компілятора, а не конфігурації під час виконання в реальному часі. +- **НЕСУМІСНО:** Використання спеціального атрибута `is` обмежено лише зарезервованим тегом ``. +- **НОВЕ:** Для підтримки випадків використання версії 2.x, коли `is` використовується на нативних елементах для обходу обмежень нативного парсингу HTML, додайте до значення префікс `vue:`, щоб відобразити його як компонент Vue. + +## Автономні користувацькі елементи + +Якщо ми хочемо додати користувацький елемент, визначений за межами Vue (наприклад, за допомогою API веб-компонентів), нам потрібно "вказати" Vue розглядати його як користувацький елемент. Давайте розглянемо для прикладу наступний шаблон. + +```html + +``` + +### 2.x Синтаксис + +У версії Vue 2.x налаштування тегів як користувацьких елементів здійснювалося за допомогою `Vue.config.ignoredElements`: + +```js +// Це змусить Vue ігнорувати користувацький елемент, визначений за межами Vue +// (наприклад, за допомогою API веб-компонентів) + +Vue.config.ignoredElements = ['plastic-button'] +``` + +### 3.x Синтаксис + +**У версії Vue 3.0 ця перевірка виконується під час компіляції шаблону.** Вказати компілятору вважати `` користувацьким елементом: + +- Передайте опцію `isCustomElement` компілятору шаблону Vue на етапі збірки. Якщо ви використовуєте `vue-loader`, це має бути передано через опцію `compilerOptions` у `vue-loader`: + + ```js + // у конфігурації webpack + rules: [ + { + test: /\.vue$/, + use: 'vue-loader', + options: { + compilerOptions: { + isCustomElement: tag => tag === 'plastic-button' + } + } + } + // ... + ] + ``` + +- Якщо ви використовуєте компіляцію шаблону на льоту, передайте його через `app.config.compilerOptions.isCustomElement`: + + ```js + const app = Vue.createApp({}) + app.config.compilerOptions.isCustomElement = tag => tag === 'plastic-button' + ``` + + Важливо зазначити, що конфігурація часу виконання впливає лише на компіляцію шаблонів під час виконання - вона не впливає на попередньо скомпільовані шаблони. + +## Індивідуальні вбудовані елементи + +Специфікація користувацьких елементів надає можливість використовувати користувацькі елементи як [Користувацькі вбудовані елементи](https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-customized-builtin-example), додавши атрибут `is` до вбудованого елемента: + +```html + +``` + +Використання спеціального атрибута `is` у Vue імітувало те, що робить рідний атрибут до того, як він став загальнодоступним у браузерах. Однак у версії 2.x його було сприйнято як рендеринг компонента Vue з назвою `plastic-button`. Це блокує використання вбудованого користувацького елемента, згаданого вище. + +У версії 3.0 ми обмежуємо спеціальне поводження Vue з атрибутом `is` лише з тегом ``. + +- При використанні у зарезервованому тегу `` він поводитиметься так само як і у версії 2.x; +- При використанні зі звичайними компонентами він поводитиметься як звичайний атрибут: + + ```html + + ``` + + - Поведінка 2.x: рендерить компонент `bar`. + - Поведінка 3.x: рендерить компонент `foo` і передає атрибут `is`. + +- При використанні на простих елементах він буде переданий до виклику `createElement` як атрибут `is`, а також відрендерений як власний атрибут. Це підтримує використання користувацьких вбудованих елементів. + + ```html + + ``` + + - Поведінка 2.x: рендерить компонент `plastic-button`. + - Поведінка 3.x: рендерить нативну кнопку за викликом + + ```js + document.createElement('button', { is: 'plastic-button' }) + ``` + +[Стяг збірки міграції: `COMPILER_IS_ON_ELEMENT`](../migration-build.html#compat-configuration) + +## `vue:` Префікс для обхідних шляхів парсингу шаблонів In-DOM + +> Примітка: цей розділ стосується лише тих випадків, коли шаблони Vue безпосередньо вписані в HTML сторінки. +> Деякі елементи HTML, такі як `
    `, `
      `, `` та `` та `
      + +
      +``` + +### 3.x Синтаксис + +Зі зміною поведінки `is` тепер потрібен префікс `vue:`, щоб розпізнати елемент як компонент Vue: + +```html + + +
      +``` + +## Стратегія міграції + +- Замініть `config.ignoredElements` на `compilerOptions` у `vue-loader` (на етапі збірки) або `app.config.compilerOptions.isCustomElement` (з компіляцією шаблону на льоту) + +- Змініть усі не-теги `` з використанням `is` на `` (для шаблонів SFC) або додайте до них префікс `vue:` (для шаблонів in-DOM). + +## Дивіться також + +- [Гід - Vue та веб-компоненти](https://ua.vuejs.org/guide/extras/web-components.html) diff --git a/src/uk/breaking-changes/data-option.md b/src/uk/breaking-changes/data-option.md new file mode 100644 index 0000000..4123ae7 --- /dev/null +++ b/src/uk/breaking-changes/data-option.md @@ -0,0 +1,128 @@ +--- +title: Опція data +badges: + - breaking +--- + +# {{ $frontmatter.title }} + +## Огляд + +- **НЕСУМІСНО**: оголошення опції компонента `data` більше не приймає звичайний JavaScript об'єкт і очікує оголошення за допомогою функції. + +- **НЕСУМІСНО**: при об'єднанні декількох значень, що повертаються `data` з міксинів або розширювачів, злиття тепер є поверхневим, а не поглибленим (об'єднуються лише властивості кореневого рівня). + +## 2.x Синтаксис + +У версії 2.x розробники могли оголошувати опцію `data` за допомогою об'єкта або функції. + +Наприклад: + +```html + + + + + +``` + +Хоча це забезпечило певну зручність з точки зору того, що кореневі екземпляри мають спільний стан, це призвело до плутанини через те, що це можливо лише для кореневого екземпляра. + +## 3.x Оновлення + +У версії 3.x опцію `data` було стандартизовано так, щоб вона приймала лише функцію, яка повертає об'єкт. + +Беручи до уваги вище наведенний приклад, тут буде можлива лише одна реалізація коду: + +```html + +``` + +## Зміна поведінки при злитті міксинів + +Крім того, коли об'єднуються `data()` та міксини в компоненті, злиття тепер виконується *неглибоко*: + +```js +const Mixin = { + data() { + return { + user: { + name: 'Jack', + id: 1 + } + } + } +} + +const CompA = { + mixins: [Mixin], + data() { + return { + user: { + id: 2 + } + } + } +} +``` + +У версії Vue 2.x результатом `$data` є: + +```json +{ + "user": { + "id": 2, + "name": "Jack" + } +} +``` + +У версії 3.0 результатом `$data` буде: + +```json +{ + "user": { + "id": 2 + } +} +``` + +[Прапорець збірки міграції: `OPTIONS_DATA_FN`](../migration-build.html#compat-configuration) + +## Стратегія міграції + +Користувачам, які звикли до оголошення об'єктів, ми рекомендуємо: + +- Вилучення спільних даних у зовнішній об'єкт і використання його як властивості в `data` +- Переписати посилання на спільні дані, щоб вони вказували на новий загальний об'єкт + +Користувачам, які звикли до глибокого злиття міксинів, ми рекомендуємо рефакторинг вашого коду, щоб уникнути такої залежності, оскільки глибоке злиття міксинів є дуже неявним і може ускладнити логіку коду для розуміння та налагодження. + +[Прапорці збірки міграції:](../migration-build.html#compat-configuration) + +- `OPTIONS_DATA_FN` +- `OPTIONS_DATA_MERGE` diff --git a/src/uk/breaking-changes/emits-option.md b/src/uk/breaking-changes/emits-option.md new file mode 100644 index 0000000..bab04d5 --- /dev/null +++ b/src/uk/breaking-changes/emits-option.md @@ -0,0 +1,97 @@ +--- +title: Опція emits +badges: + - new +--- + +# Опція `emits` + +## Огляд + +Vue 3 тепер пропонує опцію `emits`, подібну до існуючої опції `props`. Цю опцію можна використовувати для визначення подій, які компонент може випромінювати своєму батьківському компоненту. + +## Поведінка 2.x + +У Vue 2 ви можете визначити реквізити, які отримує компонент, але ви не можете оголосити, які події він може випромінювати: + +```vue + + +``` + +## Поведінка 3.x + +Подібно до реквізитів, події, які випромінює компонент, тепер можна визначити за допомогою опції `emits`: + +```vue + + +``` + +Параметр також приймає об'єкт, який дозволяє розробнику визначати валідатори для аргументів, які передаються разом із випроміненою подією, подібно до валідаторів у визначеннях `props`. + +Щоб дізнатися більше про це, прочитайте [документацію API для цієї особливості](https://vuejs.org/api/options-state.html#emits). + +## Стратегія міграції + +Настійно рекомендуємо документувати всі події, створені кожним із ваших компонентів, за допомогою `emits`. + +Це особливо важливо через [видалення модифікатора `.native`](./v-on-native-modifier-removed.md). Усі слухачі подій, які не оголошено за допомогою `emits`, тепер будуть включені в `$attrs` компонента, який за замовчуванням буде прив'язаний до кореневого вузла компонента. + +### Приклад + +Для компонентів, які повторно випромінюють рідні події своїм батькам, це призведе до запуску двох подій: + +```vue + + +``` + +Коли батьківський елемент прослуховує подію `click` на компоненті: + +```html + +``` + +тепер він буде активований _двічі_: + +- Один раз із `$emit()`. +- Один раз із власного слухача подій, застосованого до кореневого елемента. + +Тут у вас є два варіанти: + +1. Правильно оголосити подію `click`. Це корисно, якщо ви справді додаєте певну логіку до цього обробника подій у ``. +2. Вилучити повторне надсилання події, оскільки батьківський елемент тепер може легко прослуховувати власну подію, без додавання `.native`. Підходить, коли вам справді треба лише повторно випромінювати подію. + +## Дивіться також + +- [Відповідний RFC](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0030-emits-option.md) +- [Посібник з міграції - Модифікатор `.native` видалено](./v-on-native-modifier-removed.md) +- [Посібник з міграції - `$listeners` видалено](./listeners-removed.md) +- [Посібник з міграції - `$attrs` включає `class` і `style`](./attrs-includes-class-style.md) +- [Посібник з міграції - Зміни в API функцій рендерингу](./render-function-api.md) diff --git a/src/uk/breaking-changes/events-api.md b/src/uk/breaking-changes/events-api.md new file mode 100644 index 0000000..3a38e24 --- /dev/null +++ b/src/uk/breaking-changes/events-api.md @@ -0,0 +1,104 @@ +--- +badges: + - breaking +--- + +# API подій + +## Огляд + +Методи екземплярів `$on`, `$off` та `$once` видалено. Екземпляри компонентів більше не реалізують інтерфейс випромінювача подій. + +## 2.x Синтаксис + +У версії 2.x екземпляр Vue можна було використовувати для ініціювання обробників, приєднаних безпосередньо через API випромінювача подій (`$on`, `$off` та `$once`). Це могло бути використано для створення _шини подій_ для створення глобальних слухачів подій, що використовуються у всьому додатку: + +```js +// eventBus.js + +const eventBus = new Vue() + +export default eventBus +``` + +```js +// ChildComponent.vue +import eventBus from './eventBus' + +export default { + mounted() { + // додавання слухача шини подій + eventBus.$on('custom-event', () => { + console.log('Ініційовано користувацьку подію!') + }) + }, + beforeDestroy() { + // видалення слухача шини подій + eventBus.$off('custom-event') + } +} +``` + +```js +// ParentComponent.vue +import eventBus from './eventBus' + +export default { + methods: { + callGlobalCustomEvent() { + eventBus.$emit('custom-event') // коли ChildComponent змонтовано, то в консолі з'явиться повідомлення + } + } +} +``` + +## 3.x Оновлення + +Ми повністю видалили методи `$on`, `$off` та `$once` з екземпляра. Метод `$emit` все ще є частиною чинного API, оскільки він використовується для ініціювання обробників подій, які декларативно приєднані батьківським компонентом. + +## Стратегія міграції + +[Стяг збірки міграції: `INSTANCE_EVENT_EMITTER`](../migration-build.html#compat-configuration) + +У Vue 3 більше не можна використовувати ці API для прослуховування власних подій, що випромінюються компонентом зсередини. Для цього варіанту використання не існує шляху міграції. + +### Події кореневого компонента + +Статичні слухачі подій можна додати до кореневого компонента, передавши їх як реквізити до `createApp`: + +```js +createApp(App, { + // Прослуховування події 'expand' + onExpand() { + console.log('expand') + } +}) +``` + +### Шина подій + +Шаблон шини подій можна замінити за допомогою зовнішньої бібліотеки, що реалізує інтерфейс випромінювача подій, наприклад, [mitt](https://github.com/developit/mitt) або [tiny-emitter](https://github.com/scottcorgan/tiny-emitter). + +Наприклад: + +```js +// eventBus.js +import emitter from 'tiny-emitter/instance' + +export default { + $on: (...args) => emitter.on(...args), + $once: (...args) => emitter.once(...args), + $off: (...args) => emitter.off(...args), + $emit: (...args) => emitter.emit(...args) +} +``` + +Це забезпечує той самий API випромінювача подій, що й версія Vue 2. + +У більшості випадків не рекомендується використовувати глобальну шину подій для зв'язку між компонентами. Хоча це часто є найпростішим рішенням у короткостроковій перспективі, в довгостроковій перспективі це майже завжди призводить до головного болю в підтримці. Залежно від обставин, існують різні альтернативи використанню шини подій: + +* Реквізити та події повинні бути вашим першим вибором для спілкування між батьківськими та дочірніми компонентами. Дочірні компоненти можуть спілкуватися через своїх батьків. +* `Provide / inject` дозволяє компоненту обмінюватися даними з вмістом слота. Це корисно для тісно пов'язаних компонентів, які завжди використовуються разом. +* `Provide / inject` також можна використовувати для зв'язку між компонентами на великих відстанях. Це може допомогти уникнути "буріння реквізиту", коли реквізит потрібно передавати через багато рівнів компонентів, які самі не потребують цього реквізиту. +* Буріння реквізиту також можна уникнути шляхом рефакторингу з використанням слотів. Якщо проміжному компоненту не потрібні реквізити, це може вказувати на проблему з розділенням відповідальності. Введення слоту в цей компонент дозволяє батьківському компоненту створювати вміст безпосередньо, так що реквізити можуть бути передані без участі проміжного компонента. +* [Глобальне управління станом](https://ua.vuejs.org/guide/scaling-up/state-management.html), таке як [Pinia](https://pinia.vuejs.org/). diff --git a/src/uk/breaking-changes/filters.md b/src/uk/breaking-changes/filters.md new file mode 100644 index 0000000..34df5ba --- /dev/null +++ b/src/uk/breaking-changes/filters.md @@ -0,0 +1,107 @@ +--- +badges: + - removed +--- + +# Фільтри + +## Огляд + +Фільтри видалено з версії Vue 3.0 і вони більше не підтримуються. + +## 2.x Синтаксис + +У версії 2.x розробники могли використовувати фільтри для застосування загального форматування тексту. + +Наприклад: + +```html + + + +``` + +Хоча це здається зручнішим, це вимагає спеціального синтаксису, який порушує припущення, що вирази у фігурних дужках є "просто JavaScript", бо вимагає витрат на вивчення та реалізацію. + +## 3.x Оновлення + +У версії 3.x фільтри вилучено і більше не підтримуються. Натомість ми рекомендуємо замінити їх викликами методів або обчислюваними властивостями. + +Використовуючи наведений вище приклад, ось один з варіантів, як це може бути реалізовано. + +```html + + + +``` + +## Стратегія міграції + +Замість того, щоб використовувати фільтри, ми рекомендуємо замінити їх обчислювальними властивостями або методами. + +[Стяги збірки міграції:](../migration-build.html#compat-configuration) + +- `FILTERS` +- `COMPILER_FILTERS` + +### Глобальні фільтри + +Якщо ви використовуєте фільтри, які були зареєстровані глобально, а потім використовувалися в усьому вашому додатку, ймовірно, буде незручно замінити їх обчислювальними властивостями або методами в кожному окремому компоненті. + +Замість цього ви можете зробити ваші глобальні фільтри доступними для всіх компонентів за допомогою [globalProperties](https://ua.vuejs.org/api/application.html#app-config-globalproperties): + +```js +// main.js +const app = createApp(App) + +app.config.globalProperties.$filters = { + currencyUSD(value) { + return '$' + value + } +} +``` + +Потім ви можете виправити всі шаблони за допомогою цього об'єкта `$filters` ось так: + +```html + +``` + +Зауважте, що при такому підході ви можете використовувати лише методи, а не обчислювані властивості, оскільки останні мають сенс лише тоді, коли оголошені в контексті окремого компонента. diff --git a/src/uk/breaking-changes/functional-components.md b/src/uk/breaking-changes/functional-components.md new file mode 100644 index 0000000..0b8d644 --- /dev/null +++ b/src/uk/breaking-changes/functional-components.md @@ -0,0 +1,120 @@ +--- +badges: + - breaking +--- + +# Функціональні компоненти + +## Огляд + +З точки зору того, що змінилося, на високому рівні: + +- Підвищення продуктивності від 2.x для функціональних компонентів тепер незначне у 3.x, тому ми рекомендуємо просто використовувати компоненти зі збереженням стану +- Функціональні компоненти можна створити лише за допомогою простої функції, яка отримує `props` і `context` (тобто `slots`, `attrs`, `emit`) +- **НЕСУМІСНО:** Атрибут `functional` в одно-файловому компоненті (SFC) `