Vue中$attrs和$listeners

135 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情

$attrs$listeners可用于组件间的通信。

$attrs

包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外)。

当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。

官网地址:cn.vuejs.org/v2/api/#vm-…

在孙组件中,使用父组件的数据,子组件只是一个传递数据的中间件,此时可使用$attrs传值。

步骤:父组件中子组件绑定需要传递的数据->在子组件中不再用props接收来自父组件的数据->在子组件中调用孙组件,并绑定$attrs->在孙组件就能直接获取父组件中绑定的值(class 和 style 除外)。

若子组件使用props接收部分值,则该部分值就不能通过$attrs传递给孙组件。

$attrs用于记录从父组件传入子组件的所有不被props捕获以及不是classstyle的数据。

父组件:

父组件中,给子组件绑定需要传递的值。未绑定的值则不能传递下去,如数据dataList。

<template>
  <div>
   <h1>这是父组件</h1>
   <!-- 给子组件关联数据,子组件如果不用props接收,那么这些数据就作为普通的HTML特性应用在子组件的根元素上。 -->
   <son-component :dataOne="dataOne" :dataTwo="dataTwo" :dataObj="dataObj"></son-component>
  </div>
</template>

<script>
import sonComponent from '@/components/sonComponent';
export default {
  name: 'oneComponent',
  components: { sonComponent },
  data() {
    return {
      dataOne: '父组件-数据1',
      dataTwo: '父组件-数据2',
      dataObj:{
        name: '父组件',
        address: '来自于父组件'
      },
      dataList: {
        value: 'dataList'
      }
    };
  },
  methods: {
    
  },
  mounted() {
    
  },
};
</script>

<style lang="less" scoped>
</style>

子组件:

子组件中,给孙组件添加v-bind="$attrs",子组件不用props接收的值,则会通过$attrs传递给孙组件,如数据dataOne就是props接收了,所以就不能通过$attrs传递给孙组件。

<template>
  <div>
    <h1>这是子组件</h1>
    <!-- 若子组件使用props接收,则不会通过$attrs传递给孙组件 -->
    <span>props: {{ dataOne }}</span>
    <!-- 给孙组件绑定$attrs,才能将父组件的数据传递下去。 -->
    <grandson-component v-bind="$attrs"></grandson-component>
  </div>
</template>

<script>
import grandsonComponent from "@/components/grandsonComponent";
export default {
  name: 'sonComponent',
  components: { grandsonComponent },
  props: {
    dataOne: "",
  },
  data() {
    return {};
  },
  methods: {},
  mounted() {
    console.log("子组件$attrs的值",this.$attrs);
  },
};
</script>

<style lang="less" scoped>
</style>

image.png

孙组件:

使用孙组件直接使用$attrs的值。

<template>
  <div>
    <h1>这是孙组件</h1>
    <span>
      $attrs:{{ $attrs }}
    </span>
  </div>
</template>

<script>
export default {
  name: "grandsonComponent",
  data() {
    return {};
  },
  methods: {},
  mounted() {
    console.log("孙组件$attrs的值",this.$attrs);
  },
};
</script>

<style lang="less" scoped>
</style>

image.png

父->子->孙:

image.png

注意:

父->子:需要在子组件上关联需要传递的数据。

子->孙:需要给孙组件绑定$attrs

$listeners

包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。

官网地址:cn.vuejs.org/v2/api/#vm-…

步骤:在父组件中定义事件,子组件监听事件->在子组件中的孙组件添加v-on="$listeners"->孙组件触发事件

父组件:

定义事件,并在子组件上监听事件。

<template>
  <div>
   <h1>这是父组件</h1>
   <son-component  @methodOne.native="methodOne" @methodListeners="methodListeners"></son-component>
  </div>
</template>

<script>
import sonComponent from '@/components/sonComponent';
export default {
  name: 'oneComponent',
  components: { sonComponent },
  data() {
    return {
      
    };
  },
  methods: {
    // 定义父组件方法
    methodListeners(value){
      console.log('触发了父组件中的methodListeners方法',value);
    },
    methodOne(value){
      console.log('触发了父组件中的methodOne方法',value);
    }
  },
  mounted() {
    
  },
};
</script>

<style lang="less" scoped>
</style>

子组件:

在孙组件上使用v-on="$listeners"

<template>
  <div>
    <h1>这是子组件</h1>
    <grandson-component v-on="$listeners"></grandson-component>
  </div>
</template>

<script>
import grandsonComponent from "@/components/grandsonComponent";
export default {
  name: 'sonComponent',
  components: { grandsonComponent },
  data() {
    return {};
  },
  methods: {},
  mounted() {
    this.$emit('methodListeners','子组件')
    this.$emit('methodOne','子组件')
  },
};
</script>

<style lang="less" scoped>
</style>

孙组件:

使用$emit触发父组件中非.native修饰的事件。

<template>
  <div>
    <h1>这是孙组件</h1>
  </div>
</template>

<script>
export default {
  name: "grandsonComponent",
  data() {
    return {};
  },
  methods: {},
  mounted() {
    this.$emit('methodListeners','孙组件')
    this.$emit('methodOne','子组件')
  },
};
</script>

<style lang="less" scoped>
</style>

image.png

可以发现,在子和孙组件触发事件时,.native修饰器的事件是不会被触发的。