The use of $attrs and $listeners in vue

1. The attrs attribute contains all the data from the parent component (except those already declared by props)

When the parent component passes a lot of data to the child component, and the child component does not declare props to receive it, then the attrs attribute in the child component contains all the data passed by the parent component (except the ones that have been declared by props), and the child component also You can use the v−bind="attrs attribute to include all the data from the parent component (except those already declared by props), and the child component can also use the v-bind="attrs attribute to include all the data from the parent component (Except for those already declared by props), a child component can also use the form of v-bind="attrs" to pass data to its child component (grandchild component). The way the grandchild component uses $attrs is similar to its parent component.

// 父组件
<template>
  <div>
    <p>父级组件</p>
    <div>
      <button @click="changeMsg">更改数据</button>     
    </div>
    <div>子组件数据:{
   
   { fromchildData }}</div>
    <child1 ref="child1" :msg="msg" v-model="fromchildData" :msg1="msg1" :msg2="msg2" :msg3="msg3" :msg4="msg4" @childData="childData"></child1>
  </div>
</template>
<script>
import child1 from './child1.vue';
export default {
  data() {
    return {
      msg: '父组件默认值',
      msg1: 'parent数据1',
      msg2: 'parent数据2',
      msg3: 'parent数据3',
      msg4: 'parent数据4',
      fromchildData: ''
    };
  },
  components: {
    child1
  },
  methods: {
    // 点击按钮更改数据
    changeMsg() {
      this.msg = '父组件主动改变值';
    },
    // 子组件的回调方法
    childData(data) {
      this.fromchildData = data;
    },

  }
};
</script>
// 子组件 child1.vue
<template>
  <div class="child-1">
    <p>--child1组件--</p>
    <div>
      <button @click="sendData">传递数据给父组件</button>
      <button @click="getParentData">使用$parent</button>
      <button @click="setListeners">使用listeners调用父级方法</button>
    </div>
    <div>
      <el-input v-model="childStr" @input="confirm"></el-input>
      <button @click="confirm">修改v-model数据</button>
    </div>
    <div>
      <p>parent组件数据:{
   
   { msg }}</p>
      <!-- 子组件child1-child -->
      <!-- <child1-child v-bind="$attrs" v-on="$listeners"></child1-child> -->
    </div>
  </div>
</template>
<script>
export default {
  props: {
    msg: {
      type: String,
      default: ''
    },
    // 通过v-model方式传值
    value: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      childStr: 'child String'
    };
  },
  inheritAttrs: false,
  mounted() {
    console.log('child1组件获取$attrs', this.$attrs);
    console.log('child1组件获取$listeners', this.$listeners);
  },
  methods: {
    // 我们在父组件中使用v-model向child2子组件传递数据,子组件的props中使用默认的value属性接收,
    // 在子组件中利用$emit触发父组件中默认input事件,此时传递的数据便会在子组件和父组件中发生变化,这就是数据双向绑定
    // 通过$emit触发父组件的input事件,并将第二个参数作为值传递给父组件
    confirm() {
      this.$emit('input', this.childStr);
    },

    // 点击按钮,使用$emit向父组件传递数据
    sendData() {
      this.$emit('childData', '我是子组件向父组件提交的数据');
    },
    // 通过$parent方式获取父组件值
    getParentData() {
      console.log('父组件', this.$parent);
    },
    //如果存在多层级组件,无需使用emit的方式逐级向上触发事件,只需要使用$listerners就可以得到父组件中的自定义事件
    setListeners() {
      this.$listeners.childData('通过listeners调用方法');
    }
  }
};
</script>
<style scoped>
.child-1 {
  border: 1px solid red;
}
</style>

 The output of $attrs and $listeners:

 

2. The listeners attribute is similar to the attrs attribute, but the things they pass are different

 $listeners can be passed to the lower component again in the form of v-on. When the parent component defines some custom non-native events on the child component, the custom event of the parent component can be obtained through the listeners attribute inside the child component. The difference between it and attrs is obvious, attrs is used to transfer attributes.

The advantage of using listeners is that if there are multi-level components, there is no need to use emit to trigger events step by step. You only need to use $listerners to get custom events in the parent component, which is equivalent to being lazy. 

3、inheritAttrs

The parent component passes a lot of data to the child component, and the props of the child component are not fully received, then the data passed by the parent component will be rendered to the HTML. We can set inheritAttrs to false for the child component to avoid such rendering .

The attributes that do not set inheritAttrs are as follows :

 After setting inheritAttrs to false ,

 

Summarize

attrs: Used to pass attributes, except for class, style, etc., it is an object. listeners: Used to pass events, in addition to native events, it is also an object.
The two attributes attrs and listeners can solve the problem of data and event transmission between multi-layer components.
inheritAttrs solves attribute rendering of data received without props

Guess you like

Origin blog.csdn.net/lqh4188/article/details/125472754