Vue中 $attrs、$listeners使用和理解

前言

提示:Vue中 常见的组件通信方式可分为三类:

  • 父子通信
通常父子传值都是 通过prpos,子组件通过events接收
通过父链/子链 通信($parent/$chldren);
ref也可以访问实例
provide/inject
$attrs/$listeners
  • 兄弟通信
Bus;
Vuex
  • 跨级通信
Bus;
Vuex;
provide/inject
$attrs/$listeners

一、前言

示例:多组件嵌套需要传递参数,通常使用vuex,但是如果只是传递数据,使用vuex不太合理,因为vuex实现的是两个组件两个值同步改变
故而Vue提供了另一种方法 使用v-bind=“$attrs”,将父组件不被认为props特性的属性传入子组件中,通常配合listeners选项一起使用,两个出现使组件之间跨组件通信不依赖vuex和bus变得简洁业务清晰
Vue中 $attrs、$listeners使用和理解_第1张图片
A组件跟b组件的通信:(父子组件)
如上图,abc分别是嵌套的,按照常规传参方式

  • a->b通过props方式向子组件传递b->a通过在b组件中使用$emit,a组件v-on接收
  • 通过全局设置vuex方式,通过computed计算属性和commit mutaion方式时间数据获取更新,达到父子通信目的
  • Vue Event Bus 使用 Vue实例 实现事件监听发布,实现组件传值
    一般数据不需要全局的情况父子传值 用第一种就可以解决

a组件与c组件通信(跨级组件嵌套关系)

  • 使用b组件中转,a组件传递给b组件,b组件props接受再传递到c组件上,从下到上也是一次c组件emit传递,b也得emit传递,达到组件通信的效果
  • 通过Vuex全局
  • 使用Vue Event Bus实现监听和发布
  • ps:如果只是祖先向子孙传递 不需要子孙返回 provide/inject 也可以解决
    第一种方法会让代码显得冗余且不易于维护b组件只是中间站
    第二种Vuex还是大材小用,只是组件数据传递,不是数据共享
    第三种 如果不能很好的事件监听和发布管理 会导致数据流的混乱,不易于维护 ps:暂时没用过
    第四种 只能达到向内传值 孙组件返不回去

知识点

Vue中 $attrs、$listeners使用和理解_第2张图片
个人理解就是 inheritAttrs 默认是true,他继承了父组件所有的属性(除了props特定的绑定) 如果不希望继承,可以改成false 但是class跟style不会受影响
Vue中 $attrs、$listeners使用和理解_第3张图片

attrs继承了父组件所有的属性 除了prop传递的属性,一般用在子组件的子元素
Vue中 $attrs、$listeners使用和理解_第4张图片
包含了负作用域所有的监听,可以配合v-on=“$listeners” 将所有事件监听器都指向组件特定子元素

实例

A组件(App.vue)

<template>
  <div id="app">
    <!-- 此处监听了两个事件,可以在B组件或者C组件中直接触发 -->
    <child1  :pchild1="child1" :pchild2="child2" :pchild3="child3" @method1="onMethod1" @method2="onMethod2"></child1>
  </div>
</template>

<script>
import Child1 from "./Child1.vue";
export default {
  data() {
    return {
      child1:'1',
      child2: 2,
      child3:{
        name:'child3'
      }
    };
  },
  components: { Child1 },
  methods: {
    onMethod1(msg1) {
      console.log(`${msg1} running`);
    },
    onMethod2(msg2) {
      console.log(`${msg2} running`);
    },
  },
};
</script>

B组件(Child1.vue)

<template>
  <div class="child-1">
    <h2>in child1</h2>
    <p>props: {{ pchild1 }}</p>
    <p>$attrs: {{ $attrs }}</p>
    <hr/>
    <!-- 通过 v-bind 绑定$attrs属性,C组件可以直接获取到A组件中传递下来的props(除了B组件中props声明的) -->
    <!-- C组件中能直接触发test的原因在于 B组件调用C组件时 使用 v-on 绑定了$listeners 属性 -->
    <child2 v-bind="$attrs" v-on="$listeners"></child2>
  </div>
</template>

<script>
import Child2 from "./Child2.vue";
export default {
  data() {
    return {
      child1:'child1'  
    };
  },
  components: { Child2 },
  props: {
    pchild1:{
      type:String
    }
  },  
  inheritAttrs: false,
  mounted() {
    this.$emit("method1",this.child1);
  },
};
</script>

C 组件 (Child2.vue)

<template>
  <div class="child-2">
    <h2>in child2:</h2>
    <p>props: {{ pChild2 }}</p>
    <p>$attrs: {{ $attrs }}</p>
    <p>pchild3Name: {{ $attrs.pchild3.name }}</p>
    <hr/>
  </div>
</template>

<script>
export default {
  data() {
    return {
      child2:'child2'
    };
  },
  props: {
    pChild2:{
      type:String,
    }
  },
  inheritAttrs: false,
  mounted() {
    this.$emit("method2",this.child2);
  },
};
</script>

效果
Vue中 $attrs、$listeners使用和理解_第5张图片

课后小故事

假设 A组件为 祖先 它入圣后给儿子(B组件)留了三件宝物 佛怒唐莲,暴雨梨花针 虚无吞炎 并告诫子孙(C组件)宝物不可外借他人,且必须滴血认亲 这三件宝物都可唤祖,在儿子入圣的时候担心万一到时候爷爷不认识孙子咋办,于是留下了自己的血attrs,告诉他有了这个你就可以继承家产了,并且告诉他你不但可以继承家产你还可以醍醐灌顶速成入圣 listeners,故而孙组件可以调用组件的方法并且获取祖先数据

借鉴引用:Vue中 a t t r s 、 attrs、 attrslisteners 详解及使用

你可能感兴趣的:(vue,vue.js,javascript,前端)