"Transparent attribute" refers to an attribute or event listener that is passed to a component but is not declared as props or emits by the component. v-on
The most common examples are class
, style
and id
When a component is rendered with a single element as the root, the transparent attribute will be automatically added to the root element. For example, if we have a <MyButton>
component whose template looks like this:
<button>click me</button>
A parent component uses this component and passes in class
:
<MyButton class="large" />
The final rendered DOM result is:
<button class="large">click me</button>
Here, <MyButton>
it is not class
declared as a prop that it accepts, so class
it is regarded as a transparent attribute, which is automatically transparently transmitted <MyButton>
to the root element
Merger of class
pairs and style
If a child component's root element already has an class
or style
attribute, it will be merged with the value inherited from the parent component. If we change the template of the previous <MyButton>
component to this:
<!-- <MyButton> 的模板 -->
<button class="btn">click me</button>
Then the final rendered DOM result will become:
<button class="btn large">click me</button>
v-on
listener inheritance
The same rules apply to v-on
event listeners:
<MyButton @click="onClick" />
click
The listener will be added to <MyButton>
the root element, the native <button>
element. When the native <button>
is clicked, onClick
the method of the parent component will be triggered. Similarly, if the native button
element itself is v-on
bound to an event listener, both the listener and the listener inherited from the parent component will be triggered.
deep component inheritance
There are cases where a component renders another component on the root node. For example, let's refactor <MyButton>
it to render on the root node <BaseButton>
:
<!-- Template for <MyButton/>, just render another component -->
<BaseButton />
At this time, <MyButton>
the received transparent attribute will be passed on directly <BaseButton>
.
Please note:
-
The transparently transmitted attribute will not contain
<MyButton>
the declared props or the listener function foremits
the declaration eventv-on
. In other words, the declared props and listener function are<MyButton>
"consumed". -
If the transparent attribute conforms to the declaration, it can also be passed in as props
<BaseButton>
.
Disable Attributes inheritance
If you don't want a component to automatically inherit the attribute, you can set it in the component options inheritAttrs: false
.
If you use it <script setup>
, you need an extra <script>
block to write the option declaration:
<script>
// Use normal <script> to declare options
export default { inheritAttrs: false } </script><script setup>
// ...setup part logic
</script>
The most common scenario where you need to disable attribute inheritance is when the attribute needs to be applied to elements other than the root node. By setting inheritAttrs
the option to false
, you can fully control how the transparently passed attribute is used.
These transparent attributes can be $attrs
accessed directly in template expressions.
<span>Fallthrough attribute: { { $attrs }}</span>
This $attrs
object contains all other attributes except those declared by the component, such as props
, listeners , etc.emits
class
style
v-on
There are a few points to note:
-
Unlike props, passthrough attributes retain their original case in JavaScript, so
foo-bar
an attribute like this needs to$attrs['foo-bar']
be accessed via . -
An event listener like
@click
this will be exposed as a function under this object .v-on
$attrs.onClick
Now we're going to use the component example from the previous section<MyButton>
again . <button>
Sometimes we may need to wrap a layer outside the element for style <div>
:
<div class="btn-wrapper">
<button class="btn">click me</button>
</div>
We want all passthrough attributes like class
and v-on
listeners to be applied on the inner ones <button>
and not <div>
on the outer ones. We can do this by setting inheritAttrs: false
and using v-bind="$attrs"
<div class="btn-wrapper">
<button class="btn" v-bind="$attrs">click me</button>
</div>
Tip: v-bind without parameters will apply all attributes of an object to the target element as attributes.