The inheritAttrs Option in Vue
Attributes on a Vue.js component "fall through" to the displayed element by default. The top-level <div>
in the MyComponent.vue
template will inherit the class="text-5xl font-semibold"
property in the following example.
In this tutorial i will be using Tailwind CSS for my styling
//MyComponent.vue
<template>
<div>
<p>This is my Component</p>
</div>
</template>
//app.vue
<template>
<div>
<MyComponent class="text-5xl font-semibold" />
</div>
</template>
In other words, the rendered element would seem as follows.
<template>
<div class="text-5xl font-semibold" >
<p>This is my Component</p>
</div>
</template>
inheritAttrs
Vue introduces an inheritAttrs
utility only available in the options API to choose if this fall through behavior should be allowed or not. Setting inheritAttrs
to false
prevents this fall through behavior. In the following example, the <div>
in MyComponent
will not inherit the class
attribute, or any other attribute.
//MyComponent.vue
<template>
<div>
<p>This is my Component</p>
</div>
</template>
<script>
export default {
inheritAttrs: false,
}
</script>
In scenarios when you wish to construct an internal event handler that fires the user-specified event handler, inheritAttrs
comes in handy. For example, inheritAttrs
is used for our async-button
component, which when clicked performs an async
function and disables the button for the duration of the async
function. In addition to running the user-specified @click
handler, the async-button
component must execute some logic to deactivate itself.
//async-button.vue
<script>
export default {
inheritAttrs: false,
data () {
return {
status: 'init'
}
}
methods: {
// When the user clicks the button, we actually call
// the `handleClick()` method first...
async handleClick(ev) {
if (this.status === 'in_progress') {
return;
}
this.status = 'in_progress';
try {
// and the `handleClick()` method calls the user-specified
// `@click` handler. `this.$attrs` refers to the attributes
// specified on `<async-button>` in HTML.
await this.$attrs.onClick(ev);
} catch (err) {
this.status = 'error';
throw err;
}
this.status = 'success';
}
},
computed: {
// Use "selective binding". Bind all attributes _except_
// `onClick` and `disabled`, because `async-button` wraps
// those attributes. Styles and class names still fall through.
attrsToBind() {
const attrs = { ...this.$attrs };
delete attrs.onClick;
delete attrs.disabled;
return attrs;
},
isDisabled() {
return this.status === 'in_progress' || this.$attrs.disabled;
}
},
}
</script>
Below is the HTML for the async-button
component. Note that v-bind
binds any additional attributes, other than disabled
and onClick.
<button v-bind="attrsToBind" :disabled="isDisabled" @click="handleClick">
<slot></slot>
</button>
Get more information on the inheritAttrs
utility from the Vue.js Documentation page.