desh
desh

Reputation: 689

Vue JS Non prop attributes and Disabling Attribute Inheritance

I have read the docs more than 5 times and I still can't understand what is Disabling Attribute Inheritance is used for and I don't understand the example given.

I understand how props works, it is passing data from parent component to child component.

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>

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>

This will output num is 42 and total is 62. Which I understand perfectly.

However when it comes to Disabling Attribute Inheritance section , by 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:"

What does this even mean ? Does this mean that parent don't have to pass on props anymore to the child and the child can automatically pick up the props from it's parent which frankly doesn't make sense or there is no parent component altogether, they are only using child component?

From their example, props: ['label' , 'value'] , how is the child component receiving these two props without the parent component passing these props to them?

I would be very thankful if someone can use the parent and vue component analogy above to provide a simple example of what does this even mean.

Thank you.

Upvotes: 8

Views: 12319

Answers (3)

DrevanTonder
DrevanTonder

Reputation: 717

Disabling Attribute Inheritance is used when you don't want html attributes assigned to the component to be passed to the root element in a component.

Parent.vue

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

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

Child.vue

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

inheritAttrs: false prevents the root component div from inheriting the title assigned to the Child component in Parent.vue.

Now notice how I use v-bind="$attrs" on the h2 in Child.vue. $attrs contains all the attributes that would have been assigned to the root div element. Now the attributes are assigned to the h2 and not the div.

inheritAttrs: false doesn't affect props or vue attributes, it affects normal html attributes. (It also doesn't affect style and class attributes)

Base Components

By "Base Components" the docs at vuejs.org means components like buttons, inputs, etc.

Using inheritAttrs: false is really 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 allows you to do:

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

Which means that the placeholder and required attributes are applied to the input in the component and not the label.

Upvotes: 1

Vic
Vic

Reputation: 1542

Something to add

If you have multiple non-prop attributes and multiple root nodes in a component, and the non-prop attributes are meant for different elements, you can bind them like this

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

// in 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>
`

Rendered HTML

<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>

Upvotes: 0

StayCool
StayCool

Reputation: 552

If you put a random html attribute onto the component, it will appear on the rendered component. If you disable inheritance, it won't.

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

when rendered, perhaps expands to

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

but if you set inheritAttrs: false, it looks like

<div> ... stuff ... </div>

that's all there is to it.

dorkus="whatever" is still stored in the $attrs object, should we want to do something else with it.

Upvotes: 2

Related Questions