You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
> This page assumes you've already read the [Components Basics](/guide/essentials/component-basics). Read that first if you are new to components.
5
+
# Fallthrough Attributes
4
6
5
-
A component non-prop attribute is an attribute or event listener that is passed to a component, but does not have a corresponding property defined in [props](./props) or [emits](./events.html#defining-custom-events). Common examples of this include `class`, `style`, and `id` attributes. You can access those attributes via `$attrs` property.
7
+
> This page assumes you've already read the [Components Basics](/guide/essentials/component-basics). Read that first if you are new to components.
6
8
7
-
## Attribute Inheritance
9
+
A component non-prop attribute is an attribute or event listener that is passed to a component, but is not explicitly declared in [props](./props) or [emits](./events.html#defining-custom-events). Common examples of this include `class`, `style`, and `id` attributes.
8
10
9
-
When a component returns a single root node, non-prop attributes will automatically be added to the root node's attributes. For example, in the instance of a date-picker component:
11
+
These fallthrough attributes can be accessed directly in template expressions as `$attrs`:
10
12
11
-
```js
12
-
app.component('date-picker', {
13
-
template:`
14
-
<div class="date-picker">
15
-
<input type="datetime-local" />
16
-
</div>
17
-
`
18
-
})
13
+
```vue-html
14
+
<span>Fallthrough attributes: {{ $attrs }}</span>
19
15
```
20
16
21
-
In the event we need to define the status of the date-picker component via a `data-status` property, it will be applied to the root node (i.e., `div.date-picker`).
17
+
<divclass="composition-api">
22
18
23
-
```vue-html
24
-
<!-- Date-picker component with a non-prop attribute -->
// fallthrough attributes are exposed as ctx.attrs
35
+
}
36
+
}
37
37
```
38
38
39
+
</div>
40
+
41
+
<divclass="options-api">
42
+
43
+
You can also access them in JavaScript via the `$attrs` instance property:
44
+
39
45
```js
40
-
app.component('date-picker', {
46
+
exportdefault {
41
47
created() {
42
-
console.log(this.$attrs)// { onChange: () => {} }
48
+
console.log(this.$attrs)
43
49
}
44
-
})
50
+
}
45
51
```
46
52
47
-
This might be helpful when we have an HTML element with `change` event as a root element of `date-picker`.
53
+
</div>
48
54
49
-
```js
50
-
app.component('date-picker', {
51
-
template:`
52
-
<select>
53
-
<option value="1">Yesterday</option>
54
-
<option value="2">Today</option>
55
-
<option value="3">Tomorrow</option>
56
-
</select>
57
-
`
58
-
})
55
+
## Attribute Inheritance
56
+
57
+
When a component renders a single root element, fallthrough attributes will be automatically added to the root element's attributes. For example, given a `<MyButton>` component with the following template:
58
+
59
+
```vue-html
60
+
<!-- template of <MyButton> -->
61
+
<button>click me</button>
59
62
```
60
63
61
-
In this case, `change` event listener is passed from the parent component to the child and it will be triggered on native `<select>``change` event. We won't need to emit an event from the `date-picker` explicitly:
64
+
And a parent using this component with:
62
65
63
66
```vue-html
64
-
<div id="date-picker" class="demo">
65
-
<date-picker @change="showChange"></date-picker>
66
-
</div>
67
+
<MyButton class="large" />
67
68
```
68
69
69
-
```js
70
-
constapp=Vue.createApp({
71
-
methods: {
72
-
showChange(event) {
73
-
console.log(event.target.value) // will log a value of the selected option
74
-
}
75
-
}
76
-
})
70
+
The final rendered DOM would be:
71
+
72
+
```html
73
+
<buttonclass="large">click me</button>
74
+
```
75
+
76
+
### `class` and `style` Merging
77
+
78
+
If the child component's root element already has existing `class` or `style` attributes, it will be merged with the `class` and `style` values that are inherited from the parent. Suppose we change the template of `<MyButton>` in the previous example to:
79
+
80
+
```vue-html
81
+
<!-- template of <MyButton> -->
82
+
<button class="btn">click me</button>
83
+
```
84
+
85
+
Then the final rendered DOM would now become:
86
+
87
+
```html
88
+
<buttonclass="btn large">click me</button>
89
+
```
90
+
91
+
### `v-on` Listener Inheritance
92
+
93
+
Same rule applies to the event listeners:
94
+
95
+
```vue-html
96
+
<MyButton @click="onClick" />
77
97
```
78
98
99
+
The `click` listener will be added to the root element of `<MyButton>`, i.e. the native `<button>` element. When the native `<button>` is clicked, it will trigger the `onClick` method of the parent component. If the native `<button>` already has a `click` listener bound with `v-on`, then both listeners will trigger.
100
+
79
101
## Disabling Attribute Inheritance
80
102
81
103
If you do **not** want a component to automatically inherit attributes, you can set `inheritAttrs: false` in the component's options.
82
104
83
-
The common scenario for disabling an attribute inheritance is when attributes need to be applied to other elements besides the root node.
105
+
<divclass="composition-api">
84
106
85
-
By setting the `inheritAttrs` option to `false`, you can control to apply to other elements attributes to use the component's `$attrs` property, which includes all attributes not included to component `props` and `emits` properties (e.g., `class`, `style`, `v-on` listeners, etc.).
107
+
If using `<script setup>`, you will need to declare this option using a separate, normal `<script>` block:
86
108
87
-
Using our date-picker component example from the [previous section](#attribute-inheritance), in the event we need to apply all non-prop attributes to the `input` element rather than the root `div` element, this can be accomplished by using the `v-bind` shortcut.
109
+
```vue
110
+
<script>
111
+
// use normal <script> to declare options
112
+
export default {
113
+
inheritAttrs: false
114
+
}
115
+
</script>
88
116
89
-
```js{5}
90
-
app.component('date-picker', {
91
-
inheritAttrs: false,
92
-
template: `
93
-
<div class="date-picker">
94
-
<input type="datetime-local" v-bind="$attrs" />
95
-
</div>
96
-
`
97
-
})
117
+
<script setup>
118
+
// ...setup logic
119
+
</script>
98
120
```
99
121
100
-
With this new configuration, our `data-status` attribute will be applied to our `input` element!
122
+
</div>
123
+
124
+
The common scenario for disabling an attribute inheritance is when attributes need to be applied to other elements besides the root node.
125
+
126
+
By setting the `inheritAttrs` option to `false`, you can take full control over where the fallthrough attributes should be applied to. The `$attrs` object includes all attributes not included to component `props` and `emits` properties (e.g., `class`, `style`, `v-on` listeners, etc.).
127
+
128
+
Using our `<MyButton>` component example from the [previous section](#attribute-inheritance) - sometimes we may need to wrap the actual `<button>` element with an extra `<div>` for styling purposes:
101
129
102
130
```vue-html
103
-
<!-- Date-picker component with a non-prop attribute -->
We want all fallthrough attributes like `class` and `v-on` listeners to be applied to the inner `<button>`, not the outer `<div>`. We can achieve this with `inheritAttrs: false` and `v-bind="$attrs"`:
@@ -114,25 +146,21 @@ With this new configuration, our `data-status` attribute will be applied to our
114
146
Unlike single root node components, components with multiple root nodes do not have an automatic attribute fallthrough behavior. If `$attrs` are not bound explicitly, a runtime warning will be issued.
// No warnings, $attrs are passed to <main> element
131
-
app.component('custom-layout', {
132
-
template:`
133
-
<header>...</header>
134
-
<main v-bind="$attrs">...</main>
135
-
<footer>...</footer>
136
-
`
137
-
})
152
+
If `<CustomLayout>` has the following multi-root template, there will be a warning because Vue cannot be sure where to apply the fallthrough attributes:
153
+
154
+
```vue-html
155
+
<header>...</header>
156
+
<main>...</main>
157
+
<footer>...</footer>
158
+
```
159
+
160
+
The warning will be suppressed if `$attrs` is explicitly bound:
If you are not using `<script setup>`, props should be declared using the `props` option, and the props object will be passed to `setup()` as the first argument:
221
+
222
+
```js
223
+
exportdefault {
224
+
props: ['title'],
225
+
setup(props) {
226
+
console.log(props.title)
227
+
}
228
+
}
229
+
```
230
+
220
231
</div>
221
232
222
233
A component can have as many props as you like and, by default, any value can be passed to any prop.
@@ -407,7 +418,24 @@ This documents all the events that a component emits and optionally [validate th
407
418
408
419
<divclass="composition-api">
409
420
410
-
Similar to `defineProps`, `defineEmits` is also only usable in `<script setup>` and doesn't need to be imported. It returns an `emit` function that can be used to emit events in JavaScript code.
421
+
Similar to `defineProps`, `defineEmits` is also only usable in `<script setup>` and doesn't need to be imported. It returns an `emit` function that can be used to emit events in JavaScript code:
422
+
423
+
```js
424
+
constemit=defineEmits(['enlarge-text'])
425
+
426
+
emit('enlarge-text')
427
+
```
428
+
429
+
If you are not using `<script setup>`, you can declare emitted events using the `emits` option. You can access the `emit` function as a property of the setup context (passed to `setup()` as the second argument):
0 commit comments