The inheritAttrs Option in Vue
By default, attributes on the component "fall through" to the rendered element. In the following example, the top-level <div>
in the MyComponent
template will inherit the class="style-div"
attribute.
// MyComponent.js Vue.component('MyComponent', { template: `<div>Hello World</div>` }); // index.js <MyComponent class="style-div" />
In other words, the rendered element would look like the following.
<div class="style-div">Hello World</div>
inheritAttrs
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.
Vue.component('MyComponent', { inheritAttrs: false, template: `<div>Hello World</div>` });
The rendered element would look like the following.
<div class="style-div">Hello World</div>
We find inheritAttrs
is useful in cases where you want to define an internal event handler that fires the user-specified event handler. For example, we use inheritAttrs
for our async-button
component, which executes an async function when the button is clicked and disables the button for the duration of the async function. The async-button
component needs to execute some logic to disable itself, in addition to executing the user-specified @click
handler.
app.component('async-button', { data: () => ({ status: 'init' }), inheritAttrs: false, 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; } }, template: template });
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>