Skip to content

Document changes related to $attrs $listeners and v-on.native (close #526,#592) #608

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Oct 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,11 @@ const sidebar = {
'/guide/migration/array-refs',
'/guide/migration/async-components',
'/guide/migration/attribute-coercion',
'/guide/migration/attrs-includes-class-style',
'/guide/migration/custom-directives',
'/guide/migration/custom-elements-interop',
'/guide/migration/data-option',
'/guide/migration/emits-option',
'/guide/migration/events-api',
'/guide/migration/filters',
'/guide/migration/fragments',
Expand All @@ -132,10 +134,12 @@ const sidebar = {
'/guide/migration/inline-template-attribute',
'/guide/migration/key-attribute',
'/guide/migration/keycode-modifiers',
'/guide/migration/listeners-removed',
'/guide/migration/props-default-this',
'/guide/migration/render-function-api',
'/guide/migration/slots-unification',
'/guide/migration/transition',
'/guide/migration/v-on-native-modifier-removed',
'/guide/migration/v-model',
'/guide/migration/v-if-v-for',
'/guide/migration/v-bind'
Expand Down
69 changes: 69 additions & 0 deletions src/guide/migration/attrs-includes-class-style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
title: $attrs includes class & style
badges:
- breaking
---

# `$attrs` includes `class` & `style` <MigrationBadges :badges="$frontmatter.badges" />

## Overview

`$attrs` now contains _all_ attributes passed to a component, including `class` and `style`.

## 2.x Behavior

`class` and `style` attributes get some special handling in the Vue 2 virtual DOM implementation. For that reason, they are _not_ included in `$attrs`, while all other attributes are.

A side effect of this manifests when using `inheritAttrs: false`:

- Attributes in `$attrs` are no longer automatically added to the root element, leaving it to the developer to decide where to add them.
- But `class` and `style`, not being part of `$attrs`, will still be applied to the component's root element:

```vue
<template>
<label>
<input type="text" v-bind="$attrs" />
</label>
</template>
<script>
export default {
inheritAttrs: false
}
</script>
```

when used like this:

```html
<my-component id="my-id" class="my-class"></my-component>
```

...will generate this HTML:

```html
<label class="my-class">
<input type="text" id="my-id" />
</label>
```

## 3.x Behavior

`$attrs` contains _all_ attributes, which makes it easier to apply all of them to a different element. The example from above now generates the following HTML:

```html
<label>
<input type="text" id="my-id" class="my-class" />
</label>
```

## Migration Strategy

In components that use `inheritAttrs: false`, make sure that styling still works as intended. If you previously relied on the special behavior of `class` and `style`, some visuals might be broken as these attributes might now be applied to another element.

## See also

- [Relevant RFC](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0031-attr-fallthrough.md)
- [Migration guide - `$listeners` removed](./listeners-removed.md)
- [Migration guide - New Emits Option](./emits-option.md)
- [Migration guide - `.native` modifier removed](./v-on-native-modifier-removed.md)
- [Migration guide - Changes in the Render Functions API](./render-function-api.md)
97 changes: 97 additions & 0 deletions src/guide/migration/emits-option.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
title: emits Option
badges:
- new
---

# `emits` Option <MigrationBadges :badges="$frontmatter.badges" />

## Overview

Vue 3 now offers an `emits` option similar to the existing `props` option. This option can be used to define the events that a component can emit to its parent.

## 2.x Behavior

In Vue 2, you can define the props that a component received, but you can't declare which events it can emit:

```html
<template>
<div>
<p>{{ text }}</p>
<button v-on:click="$emit('accepted')">OK</button>
</div>
</template>
<script>
export default {
props: ['text']
}
</script>
```

## 3.x Behavior

Similar to props, the events that the component emits can now be defined with the `emits` option.

```html
<template>
<p>{{ text }}</p>
<button v-on:click="$emit('accepted')">OK</button>
</template>
<script>
export default {
props: ['text'],
emits: ['accepted']
}
</script>
```

The option also accepts an object notation, which allows the developer to define validators for the arguments that are passed with the emitted event, similar to validators in props definitions.

For more information on this, please read the [API documentation for this feature](../../api/options-data.md#emits).

## Migration Strategy

It is highly recommended that you document all of the emitted events by your each of components this way because of the [removal of the `.native` modifier](./v-on-native-modifier-removed.md).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The words are not quite in the right order here. I think you were aiming for:

document all of the events emitted by each of your components


All events not defined with `emits` are now added as DOM event listeners to the component's root node (unless `inheritAttrs: false` has been set).

### Example

For components that re-emit native events to their parent, this would now lead to two events being fired:

```vue
<template>
<p>{{ text }}</p>
<button v-on:click="$emit('click', $event)">OK</button>
</template>
<script>
export default {
props: ['text'],
emits: [] // without declared event
}
</script>
```

When a parent listens for the `click` event on the component:

```html
<my-button v-on:click="handleClick"></my-button>
```

it would now be triggered _twice_:

- Once from `$emit()`
- Once from a native event listener applied to the root element

Here you have two options:

1. Properly declare the `click` event. This is useful if you actually do add some logic to that event handler in `<my-button>`
2. Remove the re-emitting of the event, since the parent can now listen for the native event easily, without adding `.native`. Suitable when you really only re-emit the event anyway.

## See also

- [Relevant RFC](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0030-emits-option.md)
- [Migration guide - `.native` modifier removed](./v-on-native-modifier-removed.md)
- [Migration guide - `$listeners` removed](./listeners-removed.md)
- [Migration guide - `$attrs` includes `class` & `style` ](./attrs-includes-class-style.md)
- [Migration guide - Changes in the Render Functions API](./render-function-api.md)
10 changes: 7 additions & 3 deletions src/guide/migration/introduction.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Introduction

::: info
New to Vue.js? Check out our [Essentials Guide](/guide/introduction.html) to get started.
::: info
New to Vue.js? Check out our [Essentials Guide](/guide/introduction.html) to get started.
:::

This guide is primarily for users with prior Vue 2 experience who want to learn about the new features and changes in Vue 3. **This is not something you have to read from top to bottom before trying out Vue 3.** While it looks like a lot has changed, a lot of what you know and love about Vue is still the same; but we wanted to be as thorough as possible and provide detailed explanations and examples for every documented change.
This guide is primarily for users with prior Vue 2 experience who want to learn about the new features and changes in Vue 3. **This is not something you have to read from top to bottom before trying out Vue 3.** While it looks like a lot has changed, a lot of what you know and love about Vue is still the same; but we wanted to be as thorough as possible and provide detailed explanations and examples for every documented change.

- [Quickstart](#quickstart)
- [Notable New Features](#notable-new-features)
Expand Down Expand Up @@ -69,18 +69,22 @@ The following consists a list of breaking changes from 2.x:
- [`key` usage on `<template v-for>` and non-`v-for` nodes has changed](/guide/migration/key-attribute.html)
- [`v-if` and `v-for` precedence when used on the same element has changed](/guide/migration/v-if-v-for.html)
- [`v-bind="object"` is now order-sensitive](/guide/migration/v-bind.html)
- [`v-on:event.native` modifier has been removed](./v-on-native-modifier-removed.md)
- [`ref` inside `v-for` no longer register an array of refs](/guide/migration/array-refs.html)

### Components

- [Functional components can only be created using a plain function](/guide/migration/functional-components.html)
- [`functional` attribute on single-file component (SFC) `<template>` and `functional` component option are deprecated](/guide/migration/functional-components.html)
- [Async components now require `defineAsyncComponent` method to be created](/guide/migration/async-components.html)
- [Component events should now be declared with the `emits` option](./emits-option.md)

### Render Function

- [Render function API changed](/guide/migration/render-function-api.html)
- [`$scopedSlots` property is removed and all slots are exposed via `$slots` as functions](/guide/migration/slots-unification.html)
- [`$listeners` has been removed / merged into `$attrs`](./listeners-removed)
- [`$attrs` now includes `class` and `style` attributes](./attrs-includes-class-style.md)

### Custom Elements

Expand Down
74 changes: 74 additions & 0 deletions src/guide/migration/listeners-removed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
title: $listeners removed
badges:
- breaking
---

# `$listeners` removed <MigrationBadges :badges="$frontmatter.badges" />

## Overview

The `$listeners` object has been removed in Vue 3. Event listeners are now part of `$attrs`:

```javascript
{
text: 'this is an attribute',
onClose: () => console.log('close Event triggered')
}
```

## 2.x Syntax

In Vue 2, you can access attributes passed to your components with `this.$attrs`, and event listeners with `this.$listeners`.
In combination with `inheritAttrs: false`, they allow the developer to apply these attributes and listeners to some other element instead of the root element:

```html
<template>
<label>
<input type="text" v-bind="$attrs" v-on="$listeners" />
</label>
</template>
<script>
export default {
inheritAttrs: false
}
</script>
```

## 3.x Syntax

In Vue 3's virtual DOM, event listeners are now just attributes, prefixed with `on`, and as such are part of the `$attrs` object, so `$listeners` has been removed.

```vue
<template>
<label>
<input type="text" v-bind="$attrs" />
</label>
</template>
<script>
export default {
inheritAttrs: false
}
</script>
```

If this component received an `id` attribute and a `v-on:close` listener, the `$attrs` object will now look like this:

```javascript
{
id: 'my-input',
onClose: () => console.log('close Event triggered')
}
```

## Migration Strategy

Remove all usages of `$listeners`.

## See also

- [Relevant RFC](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0031-attr-fallthrough.md)
- [Migration guide - `$attrs`includes `class` & `style` ](./attrs-includes-class-style.md)
- [Migration guide - Changes in the Render Functions API](./render-function-api.md)
- [Migration guide - New Emits Option](./emits-option.md)
- [Migration guide - `.native` modifier removed](./v-on-native-modifier-removed.md)
57 changes: 57 additions & 0 deletions src/guide/migration/v-on-native-modifier-removed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
title: v-on.native modifier removed
badges:
- breaking
---

# `v-on.native` modifier removed <MigrationBadges :badges="$frontmatter.badges" />

## Overview

The `.native` modifier for `v-on` has been removed.

## 2.x Syntax

Event listeners passed to a component with `v-on` are by default only triggered by emitting an event with `this.$emit`. To add a native DOM listener to the child component's root element instead, the `.native` modifier can be used:

```html
<my-component
v-on:close="handleComponentEvent"
v-on:click.native="handleNativeClickEvent"
/>
```

## 3.x Syntax

The `.native` modifier for `v-on` has been removed. At the same time, the [new `emits` option](./emits-option.md) allows the child to define which events it does indeed emit.

Consequently, Vue will now add all event listeners that are _not_ defined as component-emitted events in the child as native event listeners to the child's root element (unless `inheritAttrs: false` has been set in the child's options).

```html
<my-component
v-on:close="handleComponentEvent"
v-on:click="handleNativeClickEvent"
/>
```

`MyComponent.vue`

```html
<script>
export default {
emits: ['close']
}
</script>
```

## Migration Strategy

- remove all instances of the `.native` modifier.
- ensure that all your components document their events with the `emits` option.

## See also

- [Relevant RFC](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0031-attr-fallthrough.md#v-on-listener-fallthrough)
- [Migration guide - New Emits Option](./emits-option.md)
- [Migration guide - `$listeners` removed](./listeners-removed.md)
- [Migration guide - Changes in the Render Functions API](./render-function-api.md)