vue中$attrs和$listeners 的使用

1、attrs属性就包含了所有父组件传来的数据(除开已经props声明了的)

当父组件传递了很多数据给子组件时,子组件没有声明props来进行接收,那么子组件中的attrs属性就包含了所有父组件传来的数据(除开已经props声明了的),子组件还可以使用v−bind="attrs属性就包含了所有父组件传来的数据(除开已经props声明了的),子组件还可以使用v-bind="attrs属性就包含了所有父组件传来的数据(除开已经props声明了的),子组件还可以使用v−bind="attrs"的形式向它的子组件(孙子组件)传递数据,孙子组件使用$attrs的方式和它的父组件原理类似。

// 父组件
<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>

 $attrs和$listeners的输出结果:

2、listeners属性和attrs属性类似,只是它们传递的东西不一样

 $listeners可以通过v-on的形式再次传递给下层组件,当父组件在子组件上定义了一些自定义的非原生事件时,在子组件内部可以通过listeners属性获取>父组件的自定义事件,它和attrs的区别很明显,attrs用来传递属性。

使用listeners的好处在于:如果存在多层级组件,无需使用emit的方式逐级向上触发事件,只需要使用$listerners就可以得到父组件中的自定义事件,相当于偷懒了。 

3、inheritAttrs

父组件传递了很多数据给子组件,子组件的props没有完全接收,那么父组件传递的这些数据就会渲染到HTML上,我们可以给子组件设置inheritAttrs 为false,避免这样渲染。

不设置inheritAttrs的属性如下

 设置inheritAttrs为false后

总结

attrs:用来会传递属性,除了class、style之类的,它是一个对象。 listeners:用来传递事件,除了原生事件,它也是一个对象。
attrs和listeners这两个属性可以解决多层组件之间数据和事件传递的问题。
inheritAttrs解决未使用props接收的数据的属性渲染

猜你喜欢

转载自blog.csdn.net/lqh4188/article/details/125472754