Custom properties in Vue JS and Preventing the Inheritance of Attributes

I have reviewed the documentation multiple times and still struggle to grasp the concept of Disabling Attribute Inheritance and the accompanying example.

My understanding of props is clear - it involves passing data from a parent component to a child component.

In Parent.vue:


<template>
  <div id="app">
    <Child :num="num"></Child>
  </div>
</template>

<script>
import Child from "@/components/Child";
export default {
  name: "App",
  components: {
   Child
  },
  data() {
    return {
      num: 42
    };
  }
};
</script>

In Child.vue:


<template>
  <div>
    <h2>Child</h2>
    <h4>num is {{num}}</h4>
    <div id="total">
      <h4>total is {{total}}</h4>
    </div>
  </div>
</template>
<script>
export default {
  name: "Child",
  props: {
    num: {
      type: Number,
      default: 100
    }
  },
  data() {
    return {

    };
  },
  computed: {
    total() {
      return this.num + 20;
    }
  }
};
</script>

The output will be num is 42 and total is 62, which I comprehend.

Regarding the section on Disabling Attribute Inheritance, when they mention the base component, I assume they are referring to the child components.

"This pattern allows you to use base components more like raw HTML elements, without having to care about which element is actually at its root:"

This statement confuses me. Does it imply that the parent no longer needs to pass props to the child, and instead, the child can automatically inherit props from the parent even if there is no explicit parent-child relationship?

In their example with props: ['label' , 'value'], how does the child component receive these props without them being passed explicitly by the parent component?

If someone could provide a simple example using the analogy of parent and Vue components to explain this concept, I would greatly appreciate it.

Thank you.

Answer №1

When you add a random HTML attribute to the component, it will be displayed on the rendered component. However, if you disable inheritance, this won't happen.

<my-component dorkus="whatever"></my-component>

Once rendered, it might look like this:

<div dorkus="whatever"> ... content ... </div>

But if you specify inheritAttrs: false, it will appear as:

<div> ... content ... </div>

That's all there is to it.

The attribute dorkus="whatever" is still stored in the $attrs object, in case we want to use it for something else.

Answer №2

Attribute Inheritance can be disabled to prevent passing html attributes from a component to the root element.

MainComponent.vue

<template>
  <div id="app">
    <ChildComponent title="I am the child"></ChildComponent>
  </div>
</template>

<script>
import ChildComponent from "@/components/ChildComponent";
export default {
  name: "App",
  components: {
   ChildComponent
  }
};
</script>

ChildComponent.vue

<template>
  <div>
    <h2 v-bind="$attrs">Child</h2> <!-- This h2 will inherit all the html attributes -->
  </div>
</template>
<script>
export default {
  inheritAttrs: false, // Disable attribute inheritance
  name: "Child"
};
</script>

inheritAttrs: false ensures that the root component div does not inherit the title assigned to the ChildComponent in MainComponent.vue.

In the ChildComponent.vue, v-bind="$attrs" is used on the h2 element to assign all the attributes that would have been assigned to the root div element specifically to the h2 instead.

inheritAttrs: false only affects normal html attributes, not props or vue attributes. (It also excludes style and class attributes)

Base Components

When referring to "Base Components," the documentation on vuejs.org is talking about components like buttons, inputs, etc.

Using inheritAttrs: false is particularly useful for input components:

<template>
  <label>
    {{ label }}
    <input
      v-bind="$attrs"
      v-bind:value="value"
      v-on:input="$emit('input', $event.target.value)"
    >
  </label>
</template>

<script>
export default {
  name: 'base-input',
  inheritAttrs: false,
  props: ['label', 'value'],
}
</script>

This setup allows you to utilize:

<base-input
  v-model="username"
  required
  placeholder="Enter your username"
></base-input>

Thus, the placeholder and required attributes are applied to the input within the component rather than the label.

Answer №3

Additional Information

If you find yourself with multiple non-prop attributes and several root nodes within a component, each meant for different elements, you can connect them in the following manner

<mycomponent
  data-haha="haha"
  data-hehe="hehe">
</mycomponent>

// inside the component
template: `
  <p v-bind:data-yoyo="$attrs['data-haha']">only data-haha is used, and attribute data-haha renamed to data-yoyo</p>
  <p v-bind="$attrs">all attributes here</p>
`

Displaying HTML Output

<p data-yoyo="haha">only data-haha is used, and attribute data-haha renamed to data-yoyo</p>
<p data-haha="haha" data-hehe="hehe">all attributes here</p>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring the process of iterating through arrays within an object in vue.js using the v-for directive

Is there a way to iterate through an output object using the v-for template in Vue.js? new Vue({ el: app, data: { output: { player: [1, 5, 61, 98, 15, 315, 154, 65], monster: [14, 165, 113, 19, 22], }, }, }); <script src= ...

Implementing an animation feature to facilitate the item filtering process when clicked on

I have recently developed a filter gallery and I am encountering an issue with animating the filter items when clicking on buttons. The problem with my current code is that it only toggles the animation effect rather than smoothly animating each time a but ...

The SyntaxError message indicates that there was an unexpected non-whitespace character found after the JSON data when parsing it

I received an Error message: SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data Here is the code snippet: <script> $(document).ready(function () { $('.edit1').on('change', function () { ...

Do I have to include 'document.ready()' for this JavaScript code snippet?

I am currently utilizing freemarker to dynamically generate HTML pages based on user requests. These pages contain a reference to a javascript file in the header section. Within this javascript file, there is an array that is defined. It is necessary for m ...

Increasing variable in angular template (nested ng-repeat)

I am facing a similar situation as described in the example below, and I need to generate a serial number for each row independently for each mark record. Here is the Java script Object structure: $scope.childsList = [ { id:12346, ...

Running the dev command in Vue-CLI results in an error

When attempting to run npm run dev in vue-cli, the following error is encountered: $ npm run dev > [email protected] dev /Users/den/Desktop/Test/vue/vuejs-playlist > cross-env NODE_ENV=development webpack-dev-server --open --hot sh: cross-env: c ...

Responsive React Page Design with Swiper's Breakpoints (Bootstrap Integrated)

I have integrated Swiper React with my React project. It seems that I cannot manipulate the 'slides per view' using Bootstrap directly. If it were possible, I would define the necessary columns and insert the swiper slides within them. Currently ...

How can I apply a blurred effect to the background image of a jumbotron in Bootstrap-vue without affecting the clarity of the text overlay

I need help figuring out how to blur the background image of my jumbotron without blurring the text on top. <b-container fluid class="text-center"> <div> <b-jumbotron class="jumbotron"> <p style=& ...

Can someone explain the inner workings of the Typescript property decorator?

I was recently exploring Typescript property decorators, and I encountered some unexpected behavior in the following code: function dec(hasRole: boolean) { return function (target: any, propertyName: string) { let val = target[propertyName]; ...

Is it possible to generate a form dynamically in a Vue.js HTML file based on JSON data? Check out the provided f

Currently, I am diving into the world of vue.js and experimenting with building a dynamically created form. To explain further, I have JSON files that define what input types should be included in the form; now I am figuring out how to implement this usin ...

Adding JSON data to an array for Flot Diagram

I've been struggling with the task of organizing data into an array. The existing temp array is structured as follows: tmp[0][0] = "NY" tmp[0][1] = "52" tmp[1][0] = "FL" tmp[1][1] = "25" My goal is to transfer this data into a new array called data. ...

How can I parse JSON in React using the Parse function?

I am currently working with three list components, and when I click on any item in the tree list, it displays the JSON data. However, I would prefer to view it in a parse format rather than JSON. I attempted to use let json = JSON.parse(this.props.node, n ...

What is the most efficient method for encoding and decoding extensive volumes of data for a JavaScript user?

Currently, I am in the process of developing a standalone Javascript application using Spine and Node.js to create an interactive 'number property' explorer. This application allows users to select any number and discover its various properties s ...

Transcluding an element into an ng-repeat template in AngularJS: How can it be done?

Incorporating a carousel directive involves chunking the passed in array of items and mapping it into an array of arrays of elements. This structure then generates markup resembling the pseudo code provided below: <array of arrays> <array of i ...

Display nested array objects of varying levels within VUE

How do I display nested elements on the UI when dynamically generated based on a parent element's selected option (e.g. List)? For example, in the code below, when creating a field and selecting the List option, another nested should appear, and so o ...

"A lengthy contenteditable div designed to mimic an input field, with the ability to horizontally scroll

When the input is too short for the entire text to be displayed, users have the option to horizontally scroll the text inside the input by dragging with the mouse. Is there a way to implement this functionality in a contenteditable field that appears as ...

What is the recommended return type in Typescript for a component that returns a Material-UI TableContainer?

My component is generating a Material-UI Table wrapped inside a TableContainer const DataReleaseChart = (): React.FC<?> => { return ( <TableContainer sx={{ display: 'grid', rowGap: 7, }} > ...

Text in Angular vanishes upon reopening

I have a code snippet where I am trying to allow the user to edit and save a paragraph displayed on a side panel of the main page. Although the code works fine, allowing users to update the text and see it reflected in the network upon saving, there seems ...

Tips for incorporating external JavaScript code into React components

I have been tasked with integrating a graphical widget into a React component for a project I am working on. The widget_api code provided by RIPE Stat is required to accomplish this. Previously, in HTML5, the integration was successful using the following ...

jQuery parent() Function Explained

checkout this code snippet - https://jsfiddle.net/johndoe1994/xtu09zz9/ Let me explain the functionality of the code The code contains two containers: .first and .second. The .first container has two default divs with a class of .item. The .second contai ...