Table of contents
1.
Introduction
2.
What are Non-Prop Attributes?
3.
Diving deep into Non-prop Attributes in Vue.js
4.
Using Existing Attributes to Replace/Merge
5.
Inheritance of Attributes
6.
Frequently Asked Questions 
7.
Key Takeaways
Last Updated: Mar 27, 2024

Non-Prop Attributes in Vue.js

Author Sneha Mallik
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Vue.js is a free, open-source JavaScript framework for creating user interfaces and single-page apps. Vue 3 is now in beta and may change later onwards. The latest version of the Vue front-end framework is Vue 3. It builds on Vue 2's popularity and simplicity of usage.

The most intriguing aspect of Vue is how simple it is to learn. 

A non-prop attribute in vue is provided to a component but not defined equivalent prop. While using a 3rd-party custom-input component that requires a data-tooltip attribute on the input, we can add a non-prop attribute to the component instance.

<custom-input data-tooltip="Enter the input" />
You can also try this code with Online Javascript Compiler
Run Code

This blog post will detail the non-prop attributes in Vue.js

What are Non-Prop Attributes?

An attribute or an event listener provided to a component but does not have a corresponding property defined in props or emits is referred to as a non-prop attribute. The class, style, and id properties are typical examples of non-prop attributes in Vue.js. The $attrs property gives us access to those values.

The component inherits the non-prop attributes in vue.js. For example, if we pass a data attribute to a component:

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Application</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="app">
    <component-a data-status="codingNinjas"></component-a>
  </div>
  <script>
    const app = Vue.createApp({});
    app.component("component-a", {
      template: `<p>component a</p>`
    });
    app.mount("#app");
  </script>
</body>
</html>

The rendered HTML would then be:

The component's ability to inherit characteristics automatically can be disabled.

We can accomplish this by setting the component's inheritAttrs attribute to false.

For instance, we could write:

<!DOCTYPE html>
<html lang="en">
 <head>
  <title>Application</title>
  <script src="https://unpkg.com/vue@next"></script>
 </head>
 <body>
  <div id="app">
    <component-a data-status="codingNinjas"></component-a>
  </div>
  <script>
    const app = Vue.createApp({});
    app.component("component-a", {
      inheritAttrs: false,
      template: `<p>component a</p>`
    });
    app.mount("#app");
  </script>
 </body>
</html>

The rendered HTML would then be:

The $attrs variable, however, allows us to access the attributes.

It contains all attributes not available in the props or emits properties of the component.

As a result, $attrs would have properties such as style, class, v-on listeners, etc.

Using v-bind='$attrs', we can add the attributes to a non-root component.

For instance, we could write:

<!DOCTYPE html>
<html lang="en">
 <head>
  <title>Application</title>
  <script src="https://unpkg.com/vue@next"></script>
 </head>
 <body>
  <div id="app">
    <component-a data-status="codingNinjas"></component-a>
  </div>const app = Vue.createApp({});
    app.component("component-a", {
      inheritAttrs: false,
      template: `
        <div>
          <p v-bind="$attrs">component a</p>
        </div>`
    });
    app.mount("#app");

  <script>
        </script>
 </body>
</html>

The rendered HTML would then be:

Since we disabled the automatic inheritance by setting inheritAttrs to false, the data-status attribute is on the p tag instead of the outer div.

We also used v-bind='$attrs' to add the parent's attributes to component-a's p element.

Diving deep into Non-prop Attributes in Vue.js

A non-prop attribute is one that is provided to a component but does not have a defined equivalent prop.

Vue components can accept arbitrary attributes since the authors of the component libraries don't always know how their components will be used.

For instance, consider the following code in src/index.js:

Vue.component("child", {
 template: `
  <div>     
  </div>
`
});
new Vue({
 el: "#app"
});
You can also try this code with Online Javascript Compiler
Run Code

The index.html file looks like this:

<!DOCTYPE html>
<html>
 <head>
  <title>Application</title>
  <meta charset="UTF-8" />
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
 </head>
 <body>
  <div id="app">
    <child codingNinjas="codingNinjas"></child>
  </div>
  <script src="src/index.js"></script>
 </body>
</html>

Despite the fact that our component does not explicitly accept the codingNinjas prop, Vue will not display any warnings or errors.

Using Existing Attributes to Replace/Merge

When provided into a component, the values of the class and style attributes will be combined.

For instance, consider the following code in src/index.js:

Vue.component("child", {
 template: `
  <div class='border'>     
    codingNinjas
  </div>
`
});
new Vue({
 el: "#app"
});
You can also try this code with Online Javascript Compiler
Run Code

The index.html file looks like this:

<!DOCTYPE html>
<html>
 <head>
  <title>Application</title>
  <meta charset="UTF-8" />
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">
   </script>
  <style>
    .blue-text {
      color: blue;
    }
    .border {
      border: 1px solid blue;
    }
  </style>
 </head>
 <body>
  <div id="app">
    <child class="blue-text"></child>
  </div>
  <script src="src/index.js"></script>
 </body>
</html>

Then there we obtain the following output:

Vue is smart enough to combine the two classes. The border class that we have in our component code is combined with the blue-text class that we passed in.

The value will be replaced for props other than class and style. For example, suppose we have:

Vue.component("child", {
  template: `
    <div data-codingNinjas='bar'>      
      codingNinjas
    </div>
  `
});
new Vue({
  el: "#app"
});
You can also try this code with Online Javascript Compiler
Run Code

The index.html file looks like this:

<!DOCTYPE html>
<html>
 <head>
  <title>Application</title>
  <meta charset="UTF-8" />
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
 </head>
 <body>
  <div id="app">
    <child data-codingNinjas="codingNinjas"></child>
  </div>
  <script src="src/index.js"></script>
 </body>
</html>

In the displayed output, we'll see data-codingNinjas="codingNinjas".

Inheritance of Attributes

The use of non-prop attributes in vue.js can be enhanced by attribute inheritance (and its disabling). Attributes are automatically added to the root element of your template. Consider the following scenario:

// BaseInput.vue
<template>
  <div>
    <input type="text" />
  </div>
</template>
You can also try this code with Online Javascript Compiler
Run Code
// MyComponent.vue
<BaseInput data-testid="my-component-id" />
You can also try this code with Online Javascript Compiler
Run Code

The resulted output will be:

<div data-testid="my-component-id">
  <input type="text">
</div>
You can also try this code with Online Javascript Compiler
Run Code

We can disable this default approach by setting inheritAttrs: false, which tells Vue that we'll explicitly bind the attributes where they're needed. We might want to set the properties of the input element rather than the outer div in the example above. We add the attribute v-bind="$attrs" to the input element to accomplish this.

// BaseInput.vue
<template>
  <div>
    <input type="text" v-bind="$attrs" />
  </div>
</template>

<script>
export default {
  inheritAttrs: false,
  // ...
}
</script>
You can also try this code with Online Javascript Compiler
Run Code

Now, if we use BaseInput data-testid="my-component-id" />, we'll get:

<div>
  <input type="text" data-testid="my-component-id">
</div>
You can also try this code with Online Javascript Compiler
Run Code

Frequently Asked Questions
 

  1. Are the class and style attributes applied in Vue?

Ans: ​​The class and the style attributes aren't applied to $attrs in Vue 2. Regardless of whether inheritAttrs: false is used, these two attributes are assigned to the root element—vue 3 modified this behavior by including them in $attrs.
 

2. How is disabling the attribute inheritance helpful?

Ans: Disabling the attribute inheritance is extremely helpful when all available attribute keys are unknown or tiresome to define explicitly as a prop. For example, an input element can contain various properties such as value, disabled, type, readonly, and more. Adding data-testid (or other data properties) for testing or integration with 3rd party libraries is another example.

Key Takeaways

In this blog, we have learned the concepts of non-prop attributes in Vue.js. Non-prop attributes in Vue.js components can be set without causing warnings or problems.

The child component's class and styles are merged with those provided as props. Other props are used to override the values of existing attributes.

Recommended Topic: Attributes in DBMS

We may disable this behavior by setting inheritAttrs to false in the component's settings, which will prevent attribute values from being merged or replaced.

Go through the blog Getting started with Vue.js to deeply understand the concept of Vue.js. 

Credits: GIPHY

Happy Developing!

Live masterclass