From eb63bde32b8c7254119423c1c7ba04ccd4f38132 Mon Sep 17 00:00:00 2001 From: NataliaTepluhina Date: Sun, 19 Apr 2020 19:30:10 +0300 Subject: [PATCH 01/24] feat: started with Global Config API --- src/.vuepress/config.js | 53 ++++++++++++++++++----------------- src/api/global-config.md | 60 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 25 deletions(-) create mode 100644 src/api/global-config.md diff --git a/src/.vuepress/config.js b/src/.vuepress/config.js index 537f72ad92..dcaad2faac 100644 --- a/src/.vuepress/config.js +++ b/src/.vuepress/config.js @@ -14,8 +14,8 @@ const sidebar = { '/guide/list', '/guide/events', '/guide/forms', - '/guide/component-basics', - ], + '/guide/component-basics' + ] }, { title: 'Components In-Depth', @@ -26,8 +26,8 @@ const sidebar = { '/guide/component-custom-events', '/guide/component-slots', '/guide/component-provide-inject', - '/guide/component-dynamic-async', - ], + '/guide/component-dynamic-async' + ] }, { title: 'Reusability & Composition', @@ -37,14 +37,15 @@ const sidebar = { { title: 'Migration to Vue 3', collapsable: true, - children: ['migration'], + children: ['migration'] }, { title: 'Contribute to the Docs', collapsable: true, - children: ['writing-guide'], - }, + children: ['writing-guide'] + } ], + api: ['/api/global-config'] } module.exports = { @@ -56,9 +57,10 @@ module.exports = { { href: 'https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css', - rel: 'stylesheet', - }, + rel: 'stylesheet' + } ], + ['link', { rel: 'icon', href: '/logo.png' }] ], themeConfig: { nav: [ @@ -68,17 +70,17 @@ module.exports = { items: [ { text: 'Guide', link: '/guide/introduction' }, { text: 'Style Guide', link: '/style-guide/' }, - { text: 'Tooling', link: '/tooling/' }, - ], + { text: 'Tooling', link: '/tooling/' } + ] }, - { text: 'API Reference', link: '/api/' }, + { text: 'API Reference', link: '/api/global-config' }, { text: 'Examples', ariaLabel: 'Examples Menu', items: [ { text: 'Examples', link: '/examples/' }, - { text: 'Cookbook', link: '/cookbook/' }, - ], + { text: 'Cookbook', link: '/cookbook/' } + ] }, { text: 'Community', @@ -86,16 +88,17 @@ module.exports = { items: [ { text: 'Team', link: '/community/team/' }, { text: 'Partners', link: '/community/partners/' }, - { text: 'Themes', link: '/community/themes/' }, - ], - }, + { text: 'Themes', link: '/community/themes/' } + ] + } ], sidebarDepth: 2, sidebar: { '/guide/': sidebar.guide, '/community/': sidebar.guide, + '/api/': sidebar.api }, - smoothScroll: false, + smoothScroll: false }, plugins: { '@vuepress/pwa': { @@ -103,17 +106,17 @@ module.exports = { updatePopup: { '/': { message: 'New content is available.', - buttonText: 'Refresh', - }, - }, - }, + buttonText: 'Refresh' + } + } + } }, markdown: { /** @param {import('markdown-it')} md */ - extendMarkdown: (md) => { + extendMarkdown: md => { md.options.highlight = require('./markdown/highlight')( md.options.highlight ) - }, - }, + } + } } diff --git a/src/api/global-config.md b/src/api/global-config.md new file mode 100644 index 0000000000..ebcebabaeb --- /dev/null +++ b/src/api/global-config.md @@ -0,0 +1,60 @@ +# Global Config + +`config` is an object containing Vue application global configurations. You can modify its properties listed below before mounting your application: + +```js +const app = Vue.createApp({}) + +app.config = {...} +``` + +## devtools + +- **Type:** `boolean` + +- **Default:** `true` (`false` in production builds) + +- **Usage:** + + ```js + app.config.devtools = true + ``` + + Configure whether to allow [vue-devtools](https://github.com/vuejs/vue-devtools) inspection. This option's default value is `true` in development builds and `false` in production builds. You can set it to `true` to enable inspection for production builds. + +## errorHandler + +- **Type:** `(err: unknown, instance: ComponentPublicInstance | null, info: string) => void` + +- **Default:** `undefined` + +- **Usage:** + + ```js + app.config.errorHandler = (err, vm, info) => { + // handle error + // `info` is a Vue-specific error info, e.g. which lifecycle hook + // the error was found in + } + ``` + + Assign a handler for uncaught errors during component render function and watchers. The handler gets called with the error and the Vue instance. + + > Error tracking services [Sentry](https://sentry.io/for/vue/) and [Bugsnag](https://docs.bugsnag.com/platforms/browsers/vue/) provide official integrations using this option. + +export interface AppConfig { +// (undocumented) +errorHandler?: (err: unknown, instance: ComponentPublicInstance | null, info: string) => void; +// (undocumented) +globalProperties: Record; +// (undocumented) +isCustomElement: (tag: string) => boolean; +// (undocumented) +readonly isNativeTag?: (tag: string) => boolean; +// (undocumented) +optionMergeStrategies: Record; +// (undocumented) +performance: boolean; +// (undocumented) +warnHandler?: (msg: string, instance: ComponentPublicInstance | null, trace: string) => void; +} From af57779eba595f9663001df38ddca93bd258a25e Mon Sep 17 00:00:00 2001 From: NataliaTepluhina Date: Sun, 19 Apr 2020 21:38:52 +0300 Subject: [PATCH 02/24] feat: finished global config --- src/api/global-config.md | 147 +++++++++++++++++++++++++++++++-------- src/guide/mixins.md | 4 +- 2 files changed, 119 insertions(+), 32 deletions(-) diff --git a/src/api/global-config.md b/src/api/global-config.md index ebcebabaeb..23750e0f5c 100644 --- a/src/api/global-config.md +++ b/src/api/global-config.md @@ -16,11 +16,11 @@ app.config = {...} - **Usage:** - ```js - app.config.devtools = true - ``` +```js +app.config.devtools = true +``` - Configure whether to allow [vue-devtools](https://github.com/vuejs/vue-devtools) inspection. This option's default value is `true` in development builds and `false` in production builds. You can set it to `true` to enable inspection for production builds. +Configure whether to allow [vue-devtools](https://github.com/vuejs/vue-devtools) inspection. This option's default value is `true` in development builds and `false` in production builds. You can set it to `true` to enable inspection for production builds. ## errorHandler @@ -30,31 +30,118 @@ app.config = {...} - **Usage:** - ```js - app.config.errorHandler = (err, vm, info) => { - // handle error - // `info` is a Vue-specific error info, e.g. which lifecycle hook - // the error was found in +```js +app.config.errorHandler = (err, vm, info) => { + // handle error + // `info` is a Vue-specific error info, e.g. which lifecycle hook + // the error was found in +} +``` + +Assign a handler for uncaught errors during component render function and watchers. The handler gets called with the error and the Vue instance. + +> Error tracking services [Sentry](https://sentry.io/for/vue/) and [Bugsnag](https://docs.bugsnag.com/platforms/browsers/vue/) provide official integrations using this option. + +## warnHandler + +- **Type:** `(msg: string, instance: ComponentPublicInstance | null, trace: string) => void` + +- **Default:** `undefined` + +- **Usage:** + +```js +app.config.warnHandler = function(msg, vm, trace) { + // `trace` is the component hierarchy trace +} +``` + +Assign a custom handler for runtime Vue warnings. Note this only works during development and is ignored in production. + +## globalProperties + +- **Type:** `Record` + +- **Default:** `undefined` + +- **Usage:** + +```js +app.config.globalProperties.foo = 'bar' + +app.component('child-component', { + mounted() { + console.log(this.foo) // 'bar' + } +}) +``` + +Adds a global property that can be accessed in any component instance inside the application. The component’s property will take priority when there are conflicting keys. + +This can replace Vue 2.x `Vue.prototype` extending: + +```js +// Before +Vue.prototype.$http = () => {} + +// After +const app = Vue.createApp({}) +app.config.globalProperties.$http = () => {} +``` + +## isCustomElement + +- **Type:** `(tag: string) => boolean` + +- **Default:** `undefined` + +- **Usage:** + +```js +// any element starting with 'ion-' will be recognized as a custom one +app.config.isCustomElement = tag => tag.startsWith('ion-') +``` + +Specifies a method to recognize custom elements defined outside of Vue (e.g., using the Web Components APIs). If component matches this condition, it won't need local or global registration and Vue won't throw a warning about an `Unknown custom element`. + +## optionMergeStrategies + +- **Type:** `Record` + +- **Default:** `{}` + +- **Usage:** + +```js +const app = Vue.createApp({ + mounted() { + console.log(this.$options.hello) } - ``` - - Assign a handler for uncaught errors during component render function and watchers. The handler gets called with the error and the Vue instance. - - > Error tracking services [Sentry](https://sentry.io/for/vue/) and [Bugsnag](https://docs.bugsnag.com/platforms/browsers/vue/) provide official integrations using this option. - -export interface AppConfig { -// (undocumented) -errorHandler?: (err: unknown, instance: ComponentPublicInstance | null, info: string) => void; -// (undocumented) -globalProperties: Record; -// (undocumented) -isCustomElement: (tag: string) => boolean; -// (undocumented) -readonly isNativeTag?: (tag: string) => boolean; -// (undocumented) -optionMergeStrategies: Record; -// (undocumented) -performance: boolean; -// (undocumented) -warnHandler?: (msg: string, instance: ComponentPublicInstance | null, trace: string) => void; +}) + +app.config.optionMergeStrategies.hello = (parent, child, vm) => { + return `Hello, ${child}` } + +app.mixin({ + hello: 'Vue' +}) + +// 'Hello, Vue +``` + +Define custom merging strategies for options. + +The merge strategy receives the value of that option defined on the parent and child instances as the first and second arguments, respectively. The context Vue instance is passed as the third argument. + +- **See also:** [Custom Option Merging Strategies](../guide/mixins.html#custom-option-merge-strategies) + +## performance + +- **Type:** `boolean` + +- **Default:** `false` + +- **Usage**: + +Set this to `true` to enable component init, compile, render and patch performance tracing in the browser devtool performance/timeline panel. Only works in development mode and in browsers that support the [performance.mark](https://developer.mozilla.org/en-US/docs/Web/API/Performance/mark) API. diff --git a/src/guide/mixins.md b/src/guide/mixins.md index 48df8b3b68..b0cbe035a1 100644 --- a/src/guide/mixins.md +++ b/src/guide/mixins.md @@ -154,7 +154,7 @@ app.component('test-component', { myOption: 'hello from component!' }) -app.mount('##mixins-global') +app.mount('#mixins-global') // => "hello!" // => "hello from component!" @@ -169,7 +169,7 @@ When custom options are merged, they use the default strategy which overwrites t ```js const app = Vue.createApp({}) -app.config.optionMergeStrategies.customOption = (toVal, fromVal) { +app.config.optionMergeStrategies.customOption = (toVal, fromVal) => { // return mergedVal } ``` From 541ca7b1b6a975790d38ed4832cb215a5b1088af Mon Sep 17 00:00:00 2001 From: NataliaTepluhina Date: Sat, 25 Apr 2020 16:32:13 +0300 Subject: [PATCH 03/24] feat: added component global api --- src/api/global-api.md | 35 +++++++++++++++++++++++++++++++++++ src/guide/component-basics.md | 4 ++-- 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 src/api/global-api.md diff --git a/src/api/global-api.md b/src/api/global-api.md new file mode 100644 index 0000000000..25dc191c34 --- /dev/null +++ b/src/api/global-api.md @@ -0,0 +1,35 @@ +# Global API + +In Vue 3, global APIs that globally mutate Vue's behavior are now moved to application instances created by the new `createApp` method, and their effects are now scoped to that application instance only: + +```js +import { createApp } from 'vue' + +const app = createApp({}) +``` + +Calling `createApp` returns an application instance. This instance provides an application context. The entire component tree mounted by the application instance share the same context, which provides the configurations that were previously "global" in Vue 2.x. + +## component + +- **Arguments:** + - `{string} name` + - `{PublicAPIComponent} [definition]` + +- **Usage:** + + Register or retrieve a global component. Registration also automatically sets the component's `name` with the given `name` parameter. + +``` js +import { createApp } from 'vue' + +const app = createApp({}) + +// register an options object +app.component('my-component', { /* ... */ }) + +// retrieve a registered component (always return constructor) +const MyComponent = app.component('my-component', {}) +``` + +- **See also:** [Components](../guide/component-basics) diff --git a/src/guide/component-basics.md b/src/guide/component-basics.md index 6d36059611..8d89faddb2 100644 --- a/src/guide/component-basics.md +++ b/src/guide/component-basics.md @@ -395,7 +395,7 @@ See [this sandbox](https://codepen.io/team/Vue/pen/oNXaoKy) to experiment with t Keep in mind that this attribute can be used with regular HTML elements, however they will be treated as components, which means all attributes **will be bound as DOM attributes**. For some properties such as `value` to work as you would expect, you will need to bind them using the [`.prop` modifier](TODO:../api/#v-bind). -That's all you need to know about dynamic components for now, but once you've finished reading this page and feel comfortable with its content, we recommend coming back later to read the full guide on [Dynamic & Async Components](TODO:components-dynamic-async.html). +That's all you need to know about dynamic components for now, but once you've finished reading this page and feel comfortable with its content, we recommend coming back later to read the full guide on [Dynamic & Async Components](components-dynamic-async). ## DOM Template Parsing Caveats @@ -444,4 +444,4 @@ It should be noted that **these limitations does _not_ apply if you are using st That's all you need to know about DOM template parsing caveats for now - and actually, the end of Vue's _Essentials_. Congratulations! There's still more to learn, but first, we recommend taking a break to play with Vue yourself and build something fun. -Once you feel comfortable with the knowledge you've just digested, we recommend coming back to read the full guide on [Dynamic & Async Components](TODO:components-dynamic-async.html), as well as the other pages in the Components In-Depth section of the sidebar. +Once you feel comfortable with the knowledge you've just digested, we recommend coming back to read the full guide on [Dynamic & Async Components](components-dynamic-async), as well as the other pages in the Components In-Depth section of the sidebar. From e443c430b30461b79b4d8bdd6acd3150928bb17d Mon Sep 17 00:00:00 2001 From: NataliaTepluhina Date: Sat, 25 Apr 2020 17:02:48 +0300 Subject: [PATCH 04/24] feat: added directives API --- src/.vuepress/config.js | 2 +- src/api/global-api.md | 106 +++++++++++++++++++++++++++++++++- src/guide/custom-directive.md | 2 +- 3 files changed, 107 insertions(+), 3 deletions(-) diff --git a/src/.vuepress/config.js b/src/.vuepress/config.js index dcaad2faac..9553946fed 100644 --- a/src/.vuepress/config.js +++ b/src/.vuepress/config.js @@ -45,7 +45,7 @@ const sidebar = { children: ['writing-guide'] } ], - api: ['/api/global-config'] + api: ['/api/global-config', '/api/global-api'] } module.exports = { diff --git a/src/api/global-api.md b/src/api/global-api.md index 25dc191c34..fbb0e10512 100644 --- a/src/api/global-api.md +++ b/src/api/global-api.md @@ -32,4 +32,108 @@ app.component('my-component', { /* ... */ }) const MyComponent = app.component('my-component', {}) ``` -- **See also:** [Components](../guide/component-basics) +- **See also:** [Components](../guide/component-basics.html) + +## config + +An object containing application configurations. + +- **Usage:** + +```js +import { createApp } from 'vue' +const app = createApp({}) + +app.config = {...} +``` + +- **See also:** [Global Config Properties](./global-config.html) + +## directive + +- **Arguments:** + - `{string} name` + - `{Directive} [definition]` + +- **Usage:** + + Register or retrieve a global directive. + +``` js +import { createApp } from 'vue' +const app = createApp({}) + +// register +app.directive('my-directive', { + // Directive has a set of lifecycle hooks: + // called before bound element's parent component is mounted + beforeMount() {}, + // called when bound element's parent component is mounted + mounted() {}, + // called before the containing component's VNode is updated + beforeUpdate() {}, + // called after the containing component's VNode and the VNodes of its children // have updated + updated() {}, + // called before the bound element's parent component is unmounted + beforeUnmount() {}, + // called when the bound element's parent component is unmounted + unmounted() {} +}) + +// register (function directive) +app.directive('my-directive', () => { + // this will be called as `mounted` and `updated` +}) + +// getter, return the directive definition if registered +const myDirective = app.directive('my-directive') +``` + +Directive hooks are passed these arguments: + +### el + +The element the directive is bound to. This can be used to directly manipulate the DOM. + +### binding + +An object containing the following properties. + +- `instance`: The instance of the component where directive is used. +- `value`: The value passed to the directive. For example in `v-my-directive="1 + 1"`, the value would be `2`. +- `oldValue`: The previous value, only available in `beforeUpdate` and `updated`. It is available whether or not the value has changed. +- `arg`: The argument passed to the directive, if any. For example in `v-my-directive:foo`, the arg would be `"foo"`. +- `modifiers`: An object containing modifiers, if any. For example in `v-my-directive.foo.bar`, the modifiers object would be `{ foo: true, bar: true }`. +- `dir`: an object, passed as a parameter when directive is registered. For example, in the directive + +```js +app.directive('focus', { + mounted(el) { + el.focus() + }, +}) +``` + +`dir` would be the following object: + +```js +{ + mounted(el) { + el.focus() + } +} +``` + +### vnode + +A blueprint of the real DOM element received as el argument above. See the [VNode API](TODO) for full details. + +### prevNode + +The previous virtual node, only available in the `beforeUpdate` and `updated` hooks. + +:::tip Note +Apart from `el`, you should treat these arguments as read-only and never modify them. If you need to share information across hooks, it is recommended to do so through element's [dataset](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset). +::: + +- **See also:** [Custom Directives](../guide/custom-directive.html) diff --git a/src/guide/custom-directive.md b/src/guide/custom-directive.md index 563aead6c7..e083e04e10 100644 --- a/src/guide/custom-directive.md +++ b/src/guide/custom-directive.md @@ -66,7 +66,7 @@ We'll cover VNodes in more detail [later](TODO:/render-function.html#The-Virtual - `unmounted`: called only once, when the directive is unbound from the element and the parent component is unmounted. -You can check the arguments passed into these hooks (i.e. `el`, `binding`, `vnode`, and `prevVnode`) in [Custom Directive API](TODO) +You can check the arguments passed into these hooks (i.e. `el`, `binding`, `vnode`, and `prevVnode`) in [Custom Directive API](../api/global-api.html#directive) ### Dynamic Directive Arguments From 7cd065168f7f3e309b96a37578f709e3d075c640 Mon Sep 17 00:00:00 2001 From: NataliaTepluhina Date: Sat, 25 Apr 2020 17:06:17 +0300 Subject: [PATCH 05/24] feat: added mixin API --- src/api/global-api.md | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/api/global-api.md b/src/api/global-api.md index fbb0e10512..e7ad67d7e5 100644 --- a/src/api/global-api.md +++ b/src/api/global-api.md @@ -91,11 +91,11 @@ const myDirective = app.directive('my-directive') Directive hooks are passed these arguments: -### el +#### el The element the directive is bound to. This can be used to directly manipulate the DOM. -### binding +#### binding An object containing the following properties. @@ -124,11 +124,11 @@ app.directive('focus', { } ``` -### vnode +#### vnode A blueprint of the real DOM element received as el argument above. See the [VNode API](TODO) for full details. -### prevNode +#### prevNode The previous virtual node, only available in the `beforeUpdate` and `updated` hooks. @@ -137,3 +137,14 @@ Apart from `el`, you should treat these arguments as read-only and never modify ::: - **See also:** [Custom Directives](../guide/custom-directive.html) + +## mixin + +- **Arguments:** + - `{ComponentOptions} mixin` + +- **Usage:** + + Apply a mixin globally, which will affect **every** Vue instance created afterwards in the given app (for example, child components). This can be used by plugin authors to inject custom behavior into components. **Not recommended in application code**. + +- **See also:** [Global Mixin](../guide/mixins.html#global-mixin) From 5d9ee8cad520c2d296cd686b25d4d4dd0a6bf37f Mon Sep 17 00:00:00 2001 From: NataliaTepluhina Date: Sat, 25 Apr 2020 17:18:05 +0300 Subject: [PATCH 06/24] feat: add mount API --- src/api/global-api.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/api/global-api.md b/src/api/global-api.md index e7ad67d7e5..9c94820267 100644 --- a/src/api/global-api.md +++ b/src/api/global-api.md @@ -10,6 +10,8 @@ const app = createApp({}) Calling `createApp` returns an application instance. This instance provides an application context. The entire component tree mounted by the application instance share the same context, which provides the configurations that were previously "global" in Vue 2.x. +`createApp` method returns the application instance itself so you can chain other methods after it. + ## component - **Arguments:** @@ -148,3 +150,29 @@ Apart from `el`, you should treat these arguments as read-only and never modify Apply a mixin globally, which will affect **every** Vue instance created afterwards in the given app (for example, child components). This can be used by plugin authors to inject custom behavior into components. **Not recommended in application code**. - **See also:** [Global Mixin](../guide/mixins.html#global-mixin) + +## mount + +- **Arguments:** + - `{HostElement | string} rootContainer` + - `{boolean} isHydrate` + +- **Usage:** + + Mounts a root component of the application instance on the provided DOM element. + +- **Example:** +```html + +
+ +``` + +```js +import { createApp } from 'vue' + +createApp({}).mount('#my-app') +``` + +- **See also:** + - [Lifecycle Diagram](../guide/instance.html#lifecycle-diagram) From d55decb6613bd5a43af6de3f97846065d779c95c Mon Sep 17 00:00:00 2001 From: NataliaTepluhina Date: Sat, 25 Apr 2020 17:35:05 +0300 Subject: [PATCH 07/24] feat: added unmount and use --- src/api/global-api.md | 92 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/src/api/global-api.md b/src/api/global-api.md index 9c94820267..ffac66de92 100644 --- a/src/api/global-api.md +++ b/src/api/global-api.md @@ -22,6 +22,8 @@ Calling `createApp` returns an application instance. This instance provides an a Register or retrieve a global component. Registration also automatically sets the component's `name` with the given `name` parameter. +- **Example:** + ``` js import { createApp } from 'vue' @@ -38,9 +40,11 @@ const MyComponent = app.component('my-component', {}) ## config +- **Usage:** + An object containing application configurations. -- **Usage:** +- **Example:** ```js import { createApp } from 'vue' @@ -61,6 +65,8 @@ app.config = {...} Register or retrieve a global directive. +- **Example:** + ``` js import { createApp } from 'vue' const app = createApp({}) @@ -162,6 +168,7 @@ Apart from `el`, you should treat these arguments as read-only and never modify Mounts a root component of the application instance on the provided DOM element. - **Example:** + ```html
@@ -176,3 +183,86 @@ createApp({}).mount('#my-app') - **See also:** - [Lifecycle Diagram](../guide/instance.html#lifecycle-diagram) + +## provide + +- **Arguments:** + - `{InjectionKey | string} key` + - `{T} value` + +- **Details:** + + This option is used together with [`inject`](TODO:inject) are used together to allow an ancestor component to serve as a dependency injector for all its descendants, regardless of how deep the component hierarchy is, as long as they are in the same parent chain. + + The `provide` option should be an object or a function that returns an object. This object contains the properties that are available for injection into its descendants. You can use ES2015 Symbols as keys in this object, but only in environments that natively support `Symbol` and `Reflect.ownKeys`. + + > Note: the `provide` and `inject` bindings are NOT reactive. This is intentional. However, if you pass down an observed object, properties on that object do remain reactive. + +- **Example:** + +``` js +import { createApp } from 'vue' + +const app = createApp({ + provide: { + user: 'John Doe' + } +}) + +app.component('user-card', { + inject: ['user'], + template: ` +
+ {{ user }} +
+ ` +}) +``` + +- **See also:** + - [Provide / Inject](../guide/component-provide-inject.md) + +## unmount + +- **Arguments:** + - `{HostElement | string} rootContainer` + +- **Usage:** + + Unmounts a root component of the application instance on the provided DOM element. + +- **Example:** + +```html + +
+ +``` + +```js +import { createApp } from 'vue' + +createApp({}).mount('#my-app') + +// Application will be unmounted 5 seconds after mount +setTimeout(() => app.unmount('#my-app'), 5000) +``` + +## use + +- **Arguments:** + - `{Object | Function} plugin` + +- **Usage:** + + Install a Vue.js plugin. If the plugin is an Object, it must expose an `install` method. If it is a function itself, it will be treated as the install method. The install method will be called with Vue as the argument. + + When this method is called on the same plugin multiple times, the plugin will be installed only once. + +- **See also:** [Plugins](TODO) + + + + + + From e64ebf0ea6e099de8fab4625e8d6cbb734603143 Mon Sep 17 00:00:00 2001 From: Natalia Tepluhina Date: Sun, 26 Apr 2020 07:14:18 +0300 Subject: [PATCH 08/24] Update src/api/global-api.md Co-Authored-By: Jinjiang --- src/api/global-api.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/api/global-api.md b/src/api/global-api.md index ffac66de92..13d835b343 100644 --- a/src/api/global-api.md +++ b/src/api/global-api.md @@ -153,7 +153,7 @@ Apart from `el`, you should treat these arguments as read-only and never modify - **Usage:** - Apply a mixin globally, which will affect **every** Vue instance created afterwards in the given app (for example, child components). This can be used by plugin authors to inject custom behavior into components. **Not recommended in application code**. + Apply a mixin in the whole application scope, which will affect **every** Vue instance created afterwards in the given app (for example, child components). This can be used by plugin authors to inject custom behavior into components. **Not recommended in application code**. - **See also:** [Global Mixin](../guide/mixins.html#global-mixin) @@ -265,4 +265,3 @@ setTimeout(() => app.unmount('#my-app'), 5000) - From 49ffe2359984039593d4fb035306fb9bd164d6b3 Mon Sep 17 00:00:00 2001 From: Natalia Tepluhina Date: Sun, 26 Apr 2020 16:43:59 +0300 Subject: [PATCH 09/24] Update src/api/global-config.md Co-Authored-By: Jinjiang --- src/api/global-config.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/global-config.md b/src/api/global-config.md index 23750e0f5c..dd2cf4b78e 100644 --- a/src/api/global-config.md +++ b/src/api/global-config.md @@ -130,7 +130,7 @@ app.mixin({ // 'Hello, Vue ``` -Define custom merging strategies for options. +Define merging strategies for custom options. The merge strategy receives the value of that option defined on the parent and child instances as the first and second arguments, respectively. The context Vue instance is passed as the third argument. From c4f9dd5c22be9fb54a688088d4a9e45120aec801 Mon Sep 17 00:00:00 2001 From: NataliaTepluhina Date: Sun, 26 Apr 2020 17:01:26 +0300 Subject: [PATCH 10/24] fixL changed global -> application --- src/.vuepress/config.js | 5 +++-- src/api/{global-api.md => application-api.md} | 2 +- src/api/{global-config.md => application-config.md} | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) rename src/api/{global-api.md => application-api.md} (99%) rename src/api/{global-config.md => application-config.md} (99%) diff --git a/src/.vuepress/config.js b/src/.vuepress/config.js index 9553946fed..755ab86af1 100644 --- a/src/.vuepress/config.js +++ b/src/.vuepress/config.js @@ -45,7 +45,7 @@ const sidebar = { children: ['writing-guide'] } ], - api: ['/api/global-config', '/api/global-api'] + api: ['/api/application-config', '/api/application-api'] } module.exports = { @@ -73,7 +73,7 @@ module.exports = { { text: 'Tooling', link: '/tooling/' } ] }, - { text: 'API Reference', link: '/api/global-config' }, + { text: 'API Reference', link: '/api/application-config' }, { text: 'Examples', ariaLabel: 'Examples Menu', @@ -94,6 +94,7 @@ module.exports = { ], sidebarDepth: 2, sidebar: { + collapsable: false, '/guide/': sidebar.guide, '/community/': sidebar.guide, '/api/': sidebar.api diff --git a/src/api/global-api.md b/src/api/application-api.md similarity index 99% rename from src/api/global-api.md rename to src/api/application-api.md index ffac66de92..463632bf2f 100644 --- a/src/api/global-api.md +++ b/src/api/application-api.md @@ -1,4 +1,4 @@ -# Global API +# Application API In Vue 3, global APIs that globally mutate Vue's behavior are now moved to application instances created by the new `createApp` method, and their effects are now scoped to that application instance only: diff --git a/src/api/global-config.md b/src/api/application-config.md similarity index 99% rename from src/api/global-config.md rename to src/api/application-config.md index 23750e0f5c..fe7838603b 100644 --- a/src/api/global-config.md +++ b/src/api/application-config.md @@ -1,4 +1,4 @@ -# Global Config +# Application Config `config` is an object containing Vue application global configurations. You can modify its properties listed below before mounting your application: From 828972c9cdde0a3fd6252cd86bcb081b0a64be93 Mon Sep 17 00:00:00 2001 From: NataliaTepluhina Date: Sun, 26 Apr 2020 18:31:02 +0300 Subject: [PATCH 11/24] fix: fixed types for config --- src/api/application-api.md | 34 +++++++++++++++++++++------------- src/api/application-config.md | 8 ++++---- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/api/application-api.md b/src/api/application-api.md index a37c487835..0e63830129 100644 --- a/src/api/application-api.md +++ b/src/api/application-api.md @@ -15,6 +15,7 @@ Calling `createApp` returns an application instance. This instance provides an a ## component - **Arguments:** + - `{string} name` - `{PublicAPIComponent} [definition]` @@ -24,13 +25,15 @@ Calling `createApp` returns an application instance. This instance provides an a - **Example:** -``` js +```js import { createApp } from 'vue' const app = createApp({}) // register an options object -app.component('my-component', { /* ... */ }) +app.component('my-component', { + /* ... */ +}) // retrieve a registered component (always return constructor) const MyComponent = app.component('my-component', {}) @@ -58,6 +61,7 @@ app.config = {...} ## directive - **Arguments:** + - `{string} name` - `{Directive} [definition]` @@ -67,7 +71,7 @@ app.config = {...} - **Example:** -``` js +```js import { createApp } from 'vue' const app = createApp({}) @@ -118,7 +122,7 @@ An object containing the following properties. app.directive('focus', { mounted(el) { el.focus() - }, + } }) ``` @@ -149,6 +153,7 @@ Apart from `el`, you should treat these arguments as read-only and never modify ## mixin - **Arguments:** + - `{ComponentOptions} mixin` - **Usage:** @@ -160,6 +165,7 @@ Apart from `el`, you should treat these arguments as read-only and never modify ## mount - **Arguments:** + - `{HostElement | string} rootContainer` - `{boolean} isHydrate` @@ -178,7 +184,9 @@ Apart from `el`, you should treat these arguments as read-only and never modify ```js import { createApp } from 'vue' -createApp({}).mount('#my-app') +const app = createApp({}) +// do some necessary preparations +app.mount('#my-app') ``` - **See also:** @@ -187,6 +195,7 @@ createApp({}).mount('#my-app') ## provide - **Arguments:** + - `{InjectionKey | string} key` - `{T} value` @@ -200,7 +209,7 @@ createApp({}).mount('#my-app') - **Example:** -``` js +```js import { createApp } from 'vue' const app = createApp({ @@ -211,7 +220,7 @@ const app = createApp({ app.component('user-card', { inject: ['user'], - template: ` + template: `
{{ user }}
@@ -225,6 +234,7 @@ app.component('user-card', { ## unmount - **Arguments:** + - `{HostElement | string} rootContainer` - **Usage:** @@ -242,7 +252,9 @@ app.component('user-card', { ```js import { createApp } from 'vue' -createApp({}).mount('#my-app') +const app = createApp({}) +// do some necessary preparations +app.mount('#my-app') // Application will be unmounted 5 seconds after mount setTimeout(() => app.unmount('#my-app'), 5000) @@ -251,6 +263,7 @@ setTimeout(() => app.unmount('#my-app'), 5000) ## use - **Arguments:** + - `{Object | Function} plugin` - **Usage:** @@ -260,8 +273,3 @@ setTimeout(() => app.unmount('#my-app'), 5000) When this method is called on the same plugin multiple times, the plugin will be installed only once. - **See also:** [Plugins](TODO) - - - - - diff --git a/src/api/application-config.md b/src/api/application-config.md index d91a9815c6..7992a1463f 100644 --- a/src/api/application-config.md +++ b/src/api/application-config.md @@ -24,7 +24,7 @@ Configure whether to allow [vue-devtools](https://github.com/vuejs/vue-devtools) ## errorHandler -- **Type:** `(err: unknown, instance: ComponentPublicInstance | null, info: string) => void` +- **Type:** `Function` - **Default:** `undefined` @@ -44,7 +44,7 @@ Assign a handler for uncaught errors during component render function and watche ## warnHandler -- **Type:** `(msg: string, instance: ComponentPublicInstance | null, trace: string) => void` +- **Type:** `Function` - **Default:** `undefined` @@ -60,7 +60,7 @@ Assign a custom handler for runtime Vue warnings. Note this only works during de ## globalProperties -- **Type:** `Record` +- **Type:** `[key: string]: any` - **Default:** `undefined` @@ -106,7 +106,7 @@ Specifies a method to recognize custom elements defined outside of Vue (e.g., us ## optionMergeStrategies -- **Type:** `Record` +- **Type:** `{ [key: string]: Function }` - **Default:** `{}` From 1887ca5d7a49d366f16c14ab59b33ad6b4ce1150 Mon Sep 17 00:00:00 2001 From: NataliaTepluhina Date: Sun, 26 Apr 2020 18:36:27 +0300 Subject: [PATCH 12/24] fix: fixed types for API --- src/api/application-api.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/api/application-api.md b/src/api/application-api.md index 0e63830129..34e51b9e37 100644 --- a/src/api/application-api.md +++ b/src/api/application-api.md @@ -17,7 +17,7 @@ Calling `createApp` returns an application instance. This instance provides an a - **Arguments:** - `{string} name` - - `{PublicAPIComponent} [definition]` + - `{Function | Object} [definition]` - **Usage:** @@ -63,7 +63,7 @@ app.config = {...} - **Arguments:** - `{string} name` - - `{Directive} [definition]` + - `{Function | Object} [definition]` - **Usage:** @@ -154,7 +154,7 @@ Apart from `el`, you should treat these arguments as read-only and never modify - **Arguments:** - - `{ComponentOptions} mixin` + - `{Object} mixin` - **Usage:** @@ -166,7 +166,7 @@ Apart from `el`, you should treat these arguments as read-only and never modify - **Arguments:** - - `{HostElement | string} rootContainer` + - `{Element | string} rootContainer` - `{boolean} isHydrate` - **Usage:** @@ -194,10 +194,9 @@ app.mount('#my-app') ## provide -- **Arguments:** +- **Type:** - - `{InjectionKey | string} key` - - `{T} value` + - `Object | () => Object` - **Details:** @@ -235,7 +234,7 @@ app.component('user-card', { - **Arguments:** - - `{HostElement | string} rootContainer` + - `{Element | string} rootContainer` - **Usage:** From dfa977f10c6c41bf7a1fa012c6a73e7f19ceb792 Mon Sep 17 00:00:00 2001 From: NataliaTepluhina Date: Sun, 26 Apr 2020 18:39:51 +0300 Subject: [PATCH 13/24] feat: added a note about native HTML tags --- src/api/application-config.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/api/application-config.md b/src/api/application-config.md index 7992a1463f..b38191c183 100644 --- a/src/api/application-config.md +++ b/src/api/application-config.md @@ -104,6 +104,8 @@ app.config.isCustomElement = tag => tag.startsWith('ion-') Specifies a method to recognize custom elements defined outside of Vue (e.g., using the Web Components APIs). If component matches this condition, it won't need local or global registration and Vue won't throw a warning about an `Unknown custom element`. +> Note that all native HTML and SVG tags don't need to be matched in this function - Vue parser performs this check automatically + ## optionMergeStrategies - **Type:** `{ [key: string]: Function }` From cb6eb44ea60a583b676f6d849f898b401c94327a Mon Sep 17 00:00:00 2001 From: NataliaTepluhina Date: Sun, 26 Apr 2020 19:27:26 +0300 Subject: [PATCH 14/24] feat: added options data chapter --- src/.vuepress/config.js | 16 ++- src/api/options-data.md | 239 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 251 insertions(+), 4 deletions(-) create mode 100644 src/api/options-data.md diff --git a/src/.vuepress/config.js b/src/.vuepress/config.js index af667bf3f0..93629611a5 100644 --- a/src/.vuepress/config.js +++ b/src/.vuepress/config.js @@ -45,7 +45,15 @@ const sidebar = { children: ['writing-guide'] } ], - api: ['/api/application-config', '/api/application-api'] + api: [ + '/api/application-config', + '/api/application-api', + { + title: 'Options', + collapsable: false, + children: ['/api/options-data'] + } + ] } module.exports = { @@ -89,9 +97,9 @@ module.exports = { { text: 'Team', link: '/community/team/' }, { text: 'Partners', link: '/community/partners/' }, { text: 'Join', link: '/community/join/' }, - { text: 'Themes', link: '/community/themes/' }, - ], - }, + { text: 'Themes', link: '/community/themes/' } + ] + } ], sidebarDepth: 2, sidebar: { diff --git a/src/api/options-data.md b/src/api/options-data.md new file mode 100644 index 0000000000..8919300e0e --- /dev/null +++ b/src/api/options-data.md @@ -0,0 +1,239 @@ +# Data + +## data + +- **Type:** `Function` + +- **Details:** + + The function that returns a data object for the Vue instance. **The object must be plain**: native objects such as browser API objects and prototype properties are ignored. A rule of thumb is that data should just be data - it is not recommended to observe objects with their own stateful behavior. + + Once observed, you can no longer add reactive properties to the root data object. It is therefore recommended to declare all root-level reactive properties upfront, before creating the instance. + + After the instance is created, the original data object can be accessed as `vm.$data`. The Vue instance also proxies all the properties found on the data object, so `vm.a` will be equivalent to `vm.$data.a`. + + Properties that start with `_` or `$` will **not** be proxied on the Vue instance because they may conflict with Vue's internal properties and API methods. You will have to access them as `vm.$data._property`. + +- **Example:** + + ```js + // direct instance creation + const data = { a: 1 } + + // The object is added to a Vue instance + const vm = Vue.createApp({ + data() { + return data + } + }).mount('#app') + + console.log(vm.a) // => 1 + ``` + + Note that if you use an arrow function with the `data` property, `this` won't be the component's instance, but you can still access the instance as the function's first argument: + + ```js + data: vm => ({ a: vm.myProp }) + ``` + +- **See also:** [Reactivity in Depth](TODO:../guide/reactivity.html) + +## props + +- **Type:** `Array | Object` + +- **Details:** + + A list/hash of attributes that are exposed to accept data from the parent component. It has an Array-based simple syntax and an alternative Object-based syntax that allows advanced configurations such as type checking, custom validation and default values. + + With Object-based syntax, you can use following options: + + - `type`: can be one of the following native constructors: `String`, `Number`, `Boolean`, `Array`, `Object`, `Date`, `Function`, `Symbol`, any custom constructor function or an array of those. Will check if a prop has a given type, and will throw a warning if it doesn't. [More information](../guide/component-props.html#prop-types) on prop types. + - `default`: `any` + Specifies a default value for the prop. If the prop is not passed, this value will be used instead. Object or array defaults must be returned from a factory function. + - `required`: `Boolean` + Defines if the prop is required. In a non-production environment, a console warning will be thrown if this value is truthy and the prop is not passed. + - `validator`: `Function` + Custom validator function that takes the prop value as the sole argument. In a non-production environment, a console warning will be thrown if this function returns a falsy value (i.e. the validation fails). You can read more about prop validation [here](../guide/component-props.html#prop-validation). + +- **Example:** + + ```js + const app = Vue.createApp({}) + + // simple syntax + app.component('props-demo-simple', { + props: ['size', 'myMessage'] + }) + + // object syntax with validation + app.component('props-demo-advanced', { + props: { + // type check + height: Number, + // type check plus other validations + age: { + type: Number, + default: 0, + required: true, + validator: value => { + return value >= 0 + } + } + } + }) + ``` + +- **See also:** [Props](../guide/component-props.html) + +## computed + +- **Type:** `{ [key: string]: Function | { get: Function, set: Function } }` + +- **Details:** + + Computed properties to be mixed into the Vue instance. All getters and setters have their `this` context automatically bound to the Vue instance. + + Note that if you use an arrow function with a computed property, `this` won't be the component's instance, but you can still access the instance as the function's first argument: + + ```js + computed: { + aDouble: vm => vm.a * 2 + } + ``` + + Computed properties are cached, and only re-computed on reactive dependency changes. Note that if a certain dependency is out of the instance's scope (i.e. not reactive), the computed property will **not** be updated. + +- **Example:** + + ```js + const app = Vue.createApp({ + data() { + return { a: 1 } + }, + computed: { + // get only + aDouble() { + return this.a * 2 + }, + // both get and set + aPlus: { + get() { + return this.a + 1 + }, + set(v) { + this.a = v - 1 + } + } + } + }) + + const vm = app.mount('#app') + console.log(vm.aPlus) // => 2 + vm.aPlus = 3 + console.log(vm.a) // => 2 + console.log(vm.aDouble) // => 4 + ``` + +- **See also:** [Computed Properties](../guide/computed.html) + +### methods + +- **Type:** `{ [key: string]: Function }` + +- **Details:** + + Methods to be mixed into the Vue instance. You can access these methods directly on the VM instance, or use them in directive expressions. All methods will have their `this` context automatically bound to the Vue instance. + + :::tip Note + Note that **you should not use an arrow function to define a method** (e.g. `plus: () => this.a++`). The reason is arrow functions bind the parent context, so `this` will not be the Vue instance as you expect and `this.a` will be undefined. + ::: + +- **Example:** + + ```js + const app = Vue.createApp({ + data() { + return { a: 1 } + }, + methods: { + plus() { + this.a++ + } + } + }) + + const vm = app.mount('#app') + + vm.plus() + console.log(vm.a) // => 2 + ``` + +- **See also:** [Event Handling](../guide/events.html) + +### watch + +- **Type:** `{ [key: string]: string | Function | Object | Array}` + +- **Details:** + + An object where keys are expressions to watch and values are the corresponding callbacks. The value can also be a string of a method name, or an Object that contains additional options. The Vue instance will call `$watch()` for each entry in the object at instantiation. + +- **Example:** + + ```js + var vm = new Vue({ + data: { + a: 1, + b: 2, + c: 3, + d: 4, + e: { + f: { + g: 5 + } + } + }, + watch: { + a: function(val, oldVal) { + console.log('new: %s, old: %s', val, oldVal) + }, + // string method name + b: 'someMethod', + // the callback will be called whenever any of the watched object properties change regardless of their nested depth + c: { + handler: function(val, oldVal) { + /* ... */ + }, + deep: true + }, + // the callback will be called immediately after the start of the observation + d: { + handler: 'someMethod', + immediate: true + }, + // you can pass array of callbacks, they will be called one-by-one + e: [ + 'handle1', + function handle2(val, oldVal) { + /* ... */ + }, + { + handler: function handle3(val, oldVal) { + /* ... */ + } + /* ... */ + } + ], + // watch vm.e.f's value: {g: 5} + 'e.f': function(val, oldVal) { + /* ... */ + } + } + }) + vm.a = 2 // => new: 2, old: 1 + ``` + +

Note that __you should not use an arrow function to define a watcher__ (e.g. `searchQuery: newValue => this.updateAutocomplete(newValue)`). The reason is arrow functions bind the parent context, so `this` will not be the Vue instance as you expect and `this.updateAutocomplete` will be undefined.

+ +- **See also:** [Instance Methods / Data - vm.\$watch](#vm-watch) From aef68b02e5d021ced74df1a7abd877bce8e29bed Mon Sep 17 00:00:00 2001 From: NataliaTepluhina Date: Sun, 26 Apr 2020 21:53:41 +0300 Subject: [PATCH 15/24] feat: finished options data --- src/api/options-data.md | 67 ++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/src/api/options-data.md b/src/api/options-data.md index 8919300e0e..aeef079e7c 100644 --- a/src/api/options-data.md +++ b/src/api/options-data.md @@ -137,7 +137,7 @@ - **See also:** [Computed Properties](../guide/computed.html) -### methods +## methods - **Type:** `{ [key: string]: Function }` @@ -171,7 +171,7 @@ - **See also:** [Event Handling](../guide/events.html) -### watch +## watch - **Type:** `{ [key: string]: string | Function | Object | Array}` @@ -182,58 +182,69 @@ - **Example:** ```js - var vm = new Vue({ - data: { - a: 1, - b: 2, - c: 3, - d: 4, - e: { - f: { - g: 5 - } + const app = Vue.createApp({ + data() { + return { + a: 1, + b: 2, + c: { + d: 4 + }, + e: 'test', + f: 5 } }, watch: { - a: function(val, oldVal) { - console.log('new: %s, old: %s', val, oldVal) + a(val, oldVal) { + console.log(`new: ${val}, old: ${oldVal}`) }, // string method name b: 'someMethod', // the callback will be called whenever any of the watched object properties change regardless of their nested depth c: { - handler: function(val, oldVal) { - /* ... */ + handler(val, oldVal) { + console.log('c changed') }, deep: true }, // the callback will be called immediately after the start of the observation - d: { - handler: 'someMethod', + e: { + handler(val, oldVal) { + console.log('e changed') + }, immediate: true }, // you can pass array of callbacks, they will be called one-by-one - e: [ + f: [ 'handle1', function handle2(val, oldVal) { - /* ... */ + console.log('handle2 triggered') }, { handler: function handle3(val, oldVal) { - /* ... */ + console.log('handle3 triggered') } /* ... */ } - ], - // watch vm.e.f's value: {g: 5} - 'e.f': function(val, oldVal) { - /* ... */ + ] + }, + methods: { + someMethod() { + console.log('b changed') + }, + handle1() { + console.log('handle 1 triggered') } } }) - vm.a = 2 // => new: 2, old: 1 + + const vm = app.mount('#app') + + vm.a = 3 // => new: 3, old: 1 ``` -

Note that __you should not use an arrow function to define a watcher__ (e.g. `searchQuery: newValue => this.updateAutocomplete(newValue)`). The reason is arrow functions bind the parent context, so `this` will not be the Vue instance as you expect and `this.updateAutocomplete` will be undefined.

+ ::: tip Note + Note that _you should not use an arrow function to define a watcher_ (e.g. `searchQuery: newValue => this.updateAutocomplete(newValue)`). The reason is arrow functions bind the parent context, so `this` will not be the Vue instance as you expect and `this.updateAutocomplete` will be undefined. + ::: -- **See also:** [Instance Methods / Data - vm.\$watch](#vm-watch) +- **See also:** [Watchers](../guide/computed.html#watchers) From d3d0d253d0f4da23f193c9ee14b25ed688e33332 Mon Sep 17 00:00:00 2001 From: NataliaTepluhina Date: Thu, 30 Apr 2020 21:30:05 +0300 Subject: [PATCH 16/24] feat: added options-DOM --- src/.vuepress/config.js | 2 +- src/api/options-dom.md | 65 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 src/api/options-dom.md diff --git a/src/.vuepress/config.js b/src/.vuepress/config.js index ae4360a9a6..492998c698 100644 --- a/src/.vuepress/config.js +++ b/src/.vuepress/config.js @@ -60,7 +60,7 @@ const sidebar = { { title: 'Options', collapsable: false, - children: ['/api/options-data'] + children: ['/api/options-data', '/api/options-dom'] } ] } diff --git a/src/api/options-dom.md b/src/api/options-dom.md new file mode 100644 index 0000000000..a101afa87a --- /dev/null +++ b/src/api/options-dom.md @@ -0,0 +1,65 @@ +# DOM + +## template + +- **Type:** `string` + +- **Details:** + + A string template to be used as the markup for the Vue instance. The template will **replace** the mounted element. Any existing markup inside the mounted element will be ignored, unless content distribution slots are present in the template. + + If the string starts with `#` it will be used as a `querySelector` and use the selected element's innerHTML as the template string. This allows the use of the common ` + ``` + + Note that [refs](TODO) returned from `setup` are automatically unwrapped when accessed in the template so there's no need for `.value` in templates. + +- **Usage with Render Functions / JSX** + + `setup` can also return a render function, which can directly make use of reactive state declared in the same scope: + + ```js + import { h, ref, reactive } from 'vue' + + export default { + setup() { + const count = ref(0) + const object = reactive({ foo: 'bar' }) + + return () => h('div', [count.value, object.foo]) + } + } + ``` + +- **Arguments** + + The function receives the resolved props as its first argument: + + ```js + export default { + props: { + name: String + }, + setup(props) { + console.log(props.name) + } + } + ``` + + Note this `props` object is reactive - i.e. it is updated when new props are passed in, and can be observed and reacted upon using `watchEffect` or `watch`: + + ```js + export default { + props: { + name: String + }, + setup(props) { + watchEffect(() => { + console.log(`name is: ` + props.name) + }) + } + } + ``` + + However, do NOT destructure the `props` object, as it will lose reactivity: + + ```js + export default { + props: { + name: String + }, + setup({ name }) { + watchEffect(() => { + console.log(`name is: ` + name) // Will not be reactive! + }) + } + } + ``` + + The `props` object is immutable for userland code during development (will emit warning if user code attempts to mutate it). + + The second argument provides a context object which exposes a selective list of properties that were previously exposed on `this`: + + ```js + const MyComponent = { + setup(props, context) { + context.attrs + context.slots + context.emit + } + } + ``` + + `attrs` and `slots` are proxies to the corresponding values on the internal component instance. This ensures they always expose the latest values even after updates so that we can destructure them without worrying accessing a stale reference: + + ```js + const MyComponent = { + setup(props, { attrs }) { + // a function that may get called at a later stage + function onClick() { + console.log(attrs.foo) // guaranteed to be the latest reference + } + } + } + ``` + + There are a number of reasons for placing `props` as a separate first argument instead of including it in the context: + + - It's much more common for a component to use `props` than the other properties, and very often a component uses only `props`. + + - Having `props` as a separate argument makes it easier to type it individually without messing up the types of other properties on the context. It also makes it possible to keep a consistent signature across `setup`, `render` and plain functional components with TSX support. From 4a2f1e4175c715dae1eae4f1e7dba5f1abce5500 Mon Sep 17 00:00:00 2001 From: NataliaTepluhina Date: Sat, 2 May 2020 19:31:29 +0300 Subject: [PATCH 22/24] feat: added misc to options --- src/.vuepress/config.js | 3 ++- src/api/options-composition.md | 4 +++ src/api/options-misc.md | 46 ++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/api/options-misc.md diff --git a/src/.vuepress/config.js b/src/.vuepress/config.js index c13be3532a..e35d0c14c1 100644 --- a/src/.vuepress/config.js +++ b/src/.vuepress/config.js @@ -65,7 +65,8 @@ const sidebar = { '/api/options-dom', '/api/options-lifecycle-hooks', '/api/options-assets', - '/api/options-composition' + '/api/options-composition', + '/api/options-misc' ] } ] diff --git a/src/api/options-composition.md b/src/api/options-composition.md index b5a2c176aa..375aa79a31 100644 --- a/src/api/options-composition.md +++ b/src/api/options-composition.md @@ -182,6 +182,8 @@ } ``` +- **See also:** [Provide / Inject](../guide/component-provide-inject.html) + ## setup - **Type:** `Function` @@ -315,3 +317,5 @@ The `setup` function is a new component option. It serves as the entry point for - It's much more common for a component to use `props` than the other properties, and very often a component uses only `props`. - Having `props` as a separate argument makes it easier to type it individually without messing up the types of other properties on the context. It also makes it possible to keep a consistent signature across `setup`, `render` and plain functional components with TSX support. + +- **See also:** [Composition API](TODO) diff --git a/src/api/options-misc.md b/src/api/options-misc.md new file mode 100644 index 0000000000..55cd1e415e --- /dev/null +++ b/src/api/options-misc.md @@ -0,0 +1,46 @@ +# Misc + +## name + +- **Type:** `string` + +- **Restriction:** only respected when used as a component option. + +- **Details:** + + Allow the component to recursively invoke itself in its template. Note that when a component is registered globally with `Vue.createApp({}).component({})`, the global ID is automatically set as its name. + + Another benefit of specifying a `name` option is debugging. Named components result in more helpful warning messages. Also, when inspecting an app in the [vue-devtools](https://github.com/vuejs/vue-devtools), unnamed components will show up as ``, which isn't very informative. By providing the `name` option, you will get a much more informative component tree. + +## inheritAttrs + +- **Type:** `boolean` + +- **Default:** `true` + +- **Details:** + + By default, parent scope attribute bindings that are not recognized as props will "fallthrough". This means that when we have a single-root component, these bindings will be applied to the root element of the child component as normal HTML attributes. When authoring a component that wraps a target element or another component, this may not always be the desired behavior. By setting `inheritAttrs` to `false`, this default behavior can be disabled. The attributes are available via the `$attrs` instance property and can be explicitly bound to a non-root element using `v-bind`. + + Note: this option does **not** affect `class` and `style` bindings. + +- **Usage:** + + ```js + app.component('base-input', { + inheritAttrs: false, + props: ['label', 'value'], + template: ` + + ` + }) + ``` + +- **See also:** [Disabling Attribute Inheritance](../guide/component-props.html#disabling-attribute-inheritance) From a800329e1ee4e8c4d1fa63d7cad809d2ee3683d6 Mon Sep 17 00:00:00 2001 From: NataliaTepluhina Date: Sat, 2 May 2020 19:51:40 +0300 Subject: [PATCH 23/24] fix: TODO cleanup --- src/api/application-api.md | 2 +- src/api/options-data.md | 2 +- src/api/options-lifecycle-hooks.md | 2 -- src/guide/component-props.md | 2 +- src/guide/component-registration.md | 4 ++-- src/guide/conditional.md | 4 +--- src/guide/forms.md | 2 +- src/guide/instance.md | 12 ++++++------ src/guide/list.md | 2 +- 9 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/api/application-api.md b/src/api/application-api.md index a0e800c032..8e2651ca97 100644 --- a/src/api/application-api.md +++ b/src/api/application-api.md @@ -200,7 +200,7 @@ app.mount('#my-app') - **Details:** - This option is used together with [`inject`](TODO:inject) are used together to allow an ancestor component to serve as a dependency injector for all its descendants, regardless of how deep the component hierarchy is, as long as they are in the same parent chain. + This option is [used together with `inject`](../api/options-composition.html#provide-inject) to allow an ancestor component to serve as a dependency injector for all its descendants, regardless of how deep the component hierarchy is, as long as they are in the same parent chain. The `provide` option should be an object or a function that returns an object. This object contains the properties that are available for injection into its descendants. You can use ES2015 Symbols as keys in this object, but only in environments that natively support `Symbol` and `Reflect.ownKeys`. diff --git a/src/api/options-data.md b/src/api/options-data.md index 7ae21ab37d..ad16600adf 100644 --- a/src/api/options-data.md +++ b/src/api/options-data.md @@ -36,7 +36,7 @@ data: vm => ({ a: vm.myProp }) ``` -- **See also:** [Reactivity in Depth](TODO:../guide/reactivity.html) +- **See also:** [Reactivity in Depth](../guide/reactivity.html) ## props diff --git a/src/api/options-lifecycle-hooks.md b/src/api/options-lifecycle-hooks.md index d6a3e60bc1..11a2bf0242 100644 --- a/src/api/options-lifecycle-hooks.md +++ b/src/api/options-lifecycle-hooks.md @@ -107,7 +107,6 @@ All lifecycle hooks automatically have their `this` context bound to the instanc **This hook is not called during server-side rendering.** - **See also:** - - [Built-in Components - keep-alive](TODO) - [Dynamic Components - keep-alive](../guide/component-basics.html#keep-alive) ## deactivated @@ -121,7 +120,6 @@ All lifecycle hooks automatically have their `this` context bound to the instanc **This hook is not called during server-side rendering.** - **See also:** - - [Built-in Components - keep-alive](TODO) - [Dynamic Components - keep-alive](../guide/component-basics.html#keep-alive) ## beforeUnmount diff --git a/src/guide/component-props.md b/src/guide/component-props.md index 2ae9155416..a281879a2f 100644 --- a/src/guide/component-props.md +++ b/src/guide/component-props.md @@ -311,7 +311,7 @@ app.component('my-component', { }) ``` -With `inheritAttrs: false` and `$attrs`, you can manually decide which element you want to forward attributes to, which is often desirable for [base components](TODO:../style-guide/#Base-component-names-strongly-recommended): +With `inheritAttrs: false` and `$attrs`, you can manually decide which element you want to forward attributes to, which is often desirable for [base components](../style-guide/#base-component-names-strongly-recommended): ```js app.component('base-input', { diff --git a/src/guide/component-registration.md b/src/guide/component-registration.md index f80ab4569d..58f46e5d98 100644 --- a/src/guide/component-registration.md +++ b/src/guide/component-registration.md @@ -16,14 +16,14 @@ app.component('my-component-name', { The component's name is the first argument of `app.component`. In the example above, the component's name is "my-component-name". -The name you give a component may depend on where you intend to use it. When using a component directly in the DOM (as opposed to in a string template or [single-file component](TODO: single-file-components.html)), we strongly recommend following the [W3C rules](https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name) for custom tag names: +The name you give a component may depend on where you intend to use it. When using a component directly in the DOM (as opposed to in a string template or [single-file component](TODO), we strongly recommend following the [W3C rules](https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name) for custom tag names: 1. All lowercase 2. Contains a hyphen (i.e., has multiple words connected with the hyphen symbol) By doing so, this will help you avoid conflicts with current and future HTML elements. -You can see other recommendations for component names in the [Style Guide](TODO:../style-guide/#Base-component-names-strongly-recommended). +You can see other recommendations for component names in the [Style Guide](../style-guide/#base-component-names-strongly-recommended). ### Name Casing diff --git a/src/guide/conditional.md b/src/guide/conditional.md index 78c0962a42..46dd36c805 100644 --- a/src/guide/conditional.md +++ b/src/guide/conditional.md @@ -1,7 +1,5 @@ # Conditional Rendering - - ## `v-if` The directive `v-if` is used to conditionally render a block. The block will only be rendered if the directive's expression returns a truthy value. @@ -90,7 +88,7 @@ Generally speaking, `v-if` has higher toggle costs while `v-show` has higher ini ## `v-if` with `v-for` ::: tip Note -Using `v-if` and `v-for` together is **not recommended**. See the [style guide](TODO:/v2/style-guide/#Avoid-v-if-with-v-for-essential) for further information. +Using `v-if` and `v-for` together is **not recommended**. See the [style guide](../style-guide/#avoid-v-if-with-v-for-essential) for further information. ::: When used together with `v-if`, `v-for` has a higher priority than `v-if`. See the [list rendering guide](list#v-for-with-v-if) for details. diff --git a/src/guide/forms.md b/src/guide/forms.md index 76e2e9a7da..8da0000edb 100644 --- a/src/guide/forms.md +++ b/src/guide/forms.md @@ -324,4 +324,4 @@ If you want whitespace from user input to be trimmed automatically, you can add > If you're not yet familiar with Vue's components, you can skip this for now. -HTML's built-in input types won't always meet your needs. Fortunately, Vue components allow you to build reusable inputs with completely customized behavior. These inputs even work with `v-model`! To learn more, read about [custom inputs](TODO:components.html#Using-v-model-on-Components) in the Components guide. +HTML's built-in input types won't always meet your needs. Fortunately, Vue components allow you to build reusable inputs with completely customized behavior. These inputs even work with `v-model`! To learn more, read about [custom inputs](./component-basics.html#using-v-model-on-components) in the Components guide. diff --git a/src/guide/instance.md b/src/guide/instance.md index bd273e87f9..07bfedfe1f 100644 --- a/src/guide/instance.md +++ b/src/guide/instance.md @@ -16,7 +16,7 @@ Vue.createApp(/* options */).mount('#app') Although not strictly associated with the [MVVM pattern](https://en.wikipedia.org/wiki/Model_View_ViewModel), Vue's design was partly inspired by it. As a convention, we often use the variable `vm` (short for ViewModel) to refer to our Vue instance. -When you create a Vue instance, you pass in an **options object**. The majority of this guide describes how you can use these options to create your desired behavior. For reference, you can also browse the full list of options in the [API reference](TODO:../api/#Options-Data). +When you create a Vue instance, you pass in an **options object**. The majority of this guide describes how you can use these options to create your desired behavior. For reference, you can also browse the full list of options in the [API reference](../api/options-data.html). A Vue application consists of a **root Vue instance** created with `createApp`, optionally organized into a tree of nested, reusable components. For example, a todo app's component tree might look like this: @@ -31,7 +31,7 @@ Root Instance └─ TodoListStatistics ``` -We'll talk about [the component system](TODO:components.html) in detail later. For now, just know that all Vue components are also Vue instances, and so accept the same options object (except for a few root-specific options). +We'll talk about [the component system](component-basics.html) in detail later. For now, just know that all Vue components are also Vue instances, and so accept the same options object (except for a few root-specific options). ## Data and Methods @@ -123,11 +123,9 @@ In the future, you can consult the [API reference](TODO:../api/#Instance-Propert ## Instance Lifecycle Hooks - - Each Vue instance goes through a series of initialization steps when it's created - for example, it needs to set up data observation, compile the template, mount the instance to the DOM, and update the DOM when data changes. Along the way, it also runs functions called **lifecycle hooks**, giving users the opportunity to add their own code at specific stages. -For example, the [`created`](TODO:../api/#created) hook can be used to run code after an instance is created: +For example, the [created](../api/options-lifecycle-hooks.html#created) hook can be used to run code after an instance is created: ```js Vue.createApp({ @@ -143,7 +141,7 @@ Vue.createApp({ }) ``` -There are also other hooks which will be called at different stages of the instance's lifecycle, such as [`mounted`](TODO:../api/#mounted), [`updated`](TODO:../api/#updated), and [`destroyed`](TODO:../api/#destroyed). All lifecycle hooks are called with their `this` context pointing to the Vue instance invoking it. +There are also other hooks which will be called at different stages of the instance's lifecycle, such as [mounted](../api/options-lifecycle-hooks.html#mounted), [updated](../api/options-lifecycle-hooks.html#updated), and [unmounted](../api/options-lifecycle-hooks.html#unmounted). All lifecycle hooks are called with their `this` context pointing to the Vue instance invoking it. ::: tip Don't use [arrow functions](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions) on an options property or callback, such as `created: () => console.log(this.a)` or `vm.$watch('a', newValue => this.myMethod())`. Since an arrow function doesn't have a `this`, `this` will be treated as any other variable and lexically looked up through parent scopes until found, often resulting in errors such as `Uncaught TypeError: Cannot read property of undefined` or `Uncaught TypeError: this.myMethod is not a function`. @@ -153,4 +151,6 @@ Don't use [arrow functions](https://developer.mozilla.org/en/docs/Web/JavaScript Below is a diagram for the instance lifecycle. You don't need to fully understand everything going on right now, but as you learn and build more, it will be a useful reference. +> TODO: Diagram should be changed in order to replace `beforeDestroy` and `destroyed` with `beforeUnmount` and `unmounted` respectively + diff --git a/src/guide/list.md b/src/guide/list.md index 56d3e0dd48..993c0fb224 100644 --- a/src/guide/list.md +++ b/src/guide/list.md @@ -267,7 +267,7 @@ Similar to template `v-if`, you can also use a `