preface

When multi-level component nesting needs to pass data, the common method used is through VUEX. But just passing data around without intermediate processing and using VUEX is overkill. Therefore, there are $listeners and $attrs, which are often used with inheritAttrs.

$attrs

  • Attribute passed from parent to custom child, if notpropReceive is automatically set to the outermost label inside the child component, if yesclassstyleIt will merge the outermost tagclassstyle.
  • If the child component does not want to inherit the parent component’s notpropProperty, which can be usedinheritAttrsDisable inheritance, then passv-bind="$attrs"The non from the outsidepropProperty is set to the desired tag, but this does not changeclassstyle.

InheritAttrs propertiesThe website links

2.4.0 new

  • Types: Boolean

  • Default value: true

  • Details:

    Attribute bindings, which are not recognized as props in the parent scope, are “rolled back” by default and applied to the root element of the child component as normal HTML attributes. This may not always behave as expected when writing a component that wraps one target element or another. These default behaviors are removed by setting the inheritAttrs to false. These attributes are enabled by the (also new in 2.4) instance Property $attrs, which can be explicitly bound to non-root elements by V-bind.

    Note: This option does not affect the class and style bindings.

Example:

The parent component

<template>
  <my-input
      required
      placeholder="Please enter the content"
      type="text"
      class="theme-dark"
  />
</template>

<script>
import MyInput from './child'
export default {
  name: 'parent'.components: {
    MyInput
  }
}
</script>
Copy the code

Child components

<template>
  <div>
    <input
        v-bind="$attrs"
        class="form-control"
    />
  </div>
</template>

<script>
export default {
  name: 'MyInput'.inheritAttrs: false
}
</script>
Copy the code

The child component does not accept the value passed from the parent component, nor does it have a binding, but it does have a v-bind=”$attrs” attribute, which it will automatically accept and bind

inheritAttrs: false

inheritAttrs: true

$Listeners

  • listeners: contains objects in the parent scope.nativeModifier of)v-onEvent listeners. It can go throughv-on="$listeners"Passing in internal components – useful when creating higher-level components.

Here are just two examples of native events: focue and input

/ / the parent component
<template>
  <my-input
      required
      placeholder
      class="theme-dark"
      @focue="onFocus"
      @input="onInput"
  >
  </my-input>
</template>
<script>
import MyInput from './child'
export default {
  components: {
    MyInput
  },
  methods: {
    onFocus (e) {
      console.log(e.target.value)
    },
    onInput (e) {
      console.log(e.target.value)
    }
  }
}
</script>
Copy the code
/ / child component
<template>
  <div>
    <input
        type="text"
        v-bind="$attrs"
        class="form-control"
        @focus="$emit('focus', $event)"
        @input="$emit('input', $event)"
    />
  </div>
</template>

<script>
export default {
  name: 'MyInput'.inheritAttrs: false
}
</script>
Copy the code

Native events are a hassle, and every native event needs to be bound, but v-on=”$listeners” saves a lot of trouble

 <input
        type="text"
        v-bind="$attrs"
        class="form-control"
+ v-on="$listeners"
- @focus="$emit('focus', $event)"
- @input="$emit('input', $event)"
    />
Copy the code

This one line of code solves the problem of binding all native events