Vue-常见的组件通信方式

2,430 阅读3分钟

前言

最近一直在从头开始学习vue,顺手整理一下vue组件化的相关通信方式,分析不到之处,还望各位指正。

组件化

vue组件系统提供了⼀种抽象,让我们可以使⽤独⽴可复⽤的组件来构建⼤型应⽤,任意类型的应⽤界⾯都可以抽象为⼀个组件树。组件化能提⾼开发效率⽅便重复使⽤简化调试步骤提升项⽬可维护性便于多⼈协同开发等。

组件之间常见的通信方式

1. props / $emit

父子组件通信


// 父组件
<template>
  <div>
    <span>{{ desc }}</span>
    <child1 :msg="msg" @getEmit="getEmit"></child1>
  </div>
</template>
<script>
import child1 from "@/components/child1";
export default {
  components: { child1 },
  data() {
    return {
      msg: "我是父组件的msg",
      desc:"default"
    };
  },
  methods: {
    getEmit(data) {
      this.desc = data;
    }
  }
};
</script>


// 子组件 => child1
<template>
  <div>
    <span>我是父组件传来的{{ msg }}</span>
    <button @click="getEmit"></button>
  </div>
</template>
<script>
export default {
  props: {
    msg: String
  },
  data() {
    return {
      msg: "我是父组件的msg",
      childMsg:"我是child1的msg"
    };
  },
  methods: {
    getEmit(data) {
      this.$emit("getEmit",this.childMsg)
    }
  }
};

2. eventBus

兄弟组件通信

准备条件可以分为两种方式
  
1.  npm install vue-bus / main.js中引用
    import Vue from 'vue';
    import VueBus from 'vue-bus';
    Vue.use(VueBus);
    组件中直接使用this.$bug.on()和this.$bus.emit()来做相应的处理
    
2.  创建bus.js,该文件内写入
    import Vue from "vue";
    export default new Vue();

// 子组件 => child2
// 这里采用了第二种创建bus.js的方法,然后在该组件内引用
<template>
  <div>
    <button @click="handleSendToChild3">{{ msg }}</button>
  </div>
</template>
<script>
import Bus from "@/components/bus.js";
export default {
  data() {
    return {
      msg: "点我向child3组件传参",
      childMsg:"我是child1的msg"
    };
  },
  methods: {
    handleSendToChild3(data) {
      Bus.$emit("getData",this.childMsg)
    }
  }
};


// 子组件 => child3
// 这里采用了第二种创建bus.js的方法,然后在该组件内引用
<template>
  <div>
   <span>{{ msg }}</span>
  </div>
</template>
<script>
import Bus from "@/components/bus.js";
export default {
  data() {
    return {
      msg: "",
     
    };
  },
  methods: {
    handleSendToChild3(data) {
      Bus.$on("getData",(data)=>{
          this.msg = data
      })
    }
  }
};

3. $attrs / $listeners

父 => 子 => 孙组件通信

其中子组件只做数据传递
多级组件嵌套需要传递数据时,如果仅仅是传递数据,而不做中间处理,可以使用这种方法
$attrs:没有被子组件组册prop,$listener:子组件可以触发父组件的非.native事件

// 父组件
<template>
  <div>
    <span>{{ desc }}</span>
    <child1 :msg="msg" @getEmit="getEmit" v-on="$listener"></child1>
  </div>
</template>
<script>
import child1 from "@/components/child1";
export default {
  components: { child1 },
  data() {
    return {
      msg: "我是父组件的msg",
      desc:""
    };
  },
  methods: {
    getEmit(data) {
      this.desc = data;
    }
  }
};
</script>


// 子组件 => child1 => 相对于child2组件,该组件为兄弟组件
<template>
  <div>
    <child2 v-bind="$attrs"></child2>
  </div>
</template>
<script>
import child2 from "@/components/child2
export default {
 // inheritAttrs:false,不会把未被注册的 prop 呈现为普通的 HTML 属性 ,也就是:prop="data" prop不会作为html的新属性
  inheritAttrs: false,
  components: { child2 },
  data() {
    return {
      msg: "我是父组件的msg",
      childMsg:"我是child1的msg"
    };
  },
  mounted(){
      this.$emit("getEmit",this.childMsg);
  }
 
};


// 子组件 => child2 => 相对比child1组件,该组件为兄弟组件
<template>
  <div>
    <span>{{ msg }} {{ $attrs.msg }}</span>
  </div>
</template>
<script>
export default {
  data() {
    return {
      msg: "该组件拿到父组件通过child1组件传递过来的值 => ",
    };
  },
};

4. provide / inject

父 => 子、父 => 孙组件通信

    这种官方不推荐使用,但是,在我们写UI组件库的时候就往往很有用了,详见elementUI的部分源码(如form表单),这里我准备后续在此基础之上再进一步展开

// 父组件
<template>
  <div>
    <span>{{ desc }}</span>
    <child1 :msg="msg"></child1>
  </div>
</template>
<script>
import child1 from "@/components/child1";
export default {
  provide:{
    desc:this.desc // 这里不接收动态传参,但是可以直接传this过去,从而实现动态响应式
  }
  components: { child1 },
  data() {
    return {
      msg: "我是父组件的msg",
      desc:"我是父组件的desc"
    };
  }
};
</script>

// child1部分代码上面已经赘述过多,此处省略
// 孙组件 =>  grandson1
<template>
  <div>
    <span>{{ desc }}</span>
  </div>
</template>
<script>
export default {
  inject:['desc'],
};
</script>

5. $ref

父子组件通信


// 父组件
<template>
  <div>
    <child1 ref="sendMsg"></child1>
  </div>
</template>
<script>
import child1 from "@/components/child1";
export default {
  components: { child1 },
  data() {
    return {
      msg: "我是父组件的msg",
    };
  },
  mounted() {
      this.refs.sendMsg.handleSendToChild1(this.msg)
  }
};
</script>


// 子组件 => child1
<template>
  <div>
    <span>{{ msg }} </span>
  </div>
</template>
<script>
export default {
  data() {
    return {
      msg: "",
    };
  },
  methods: {
    handleSendToChild1(data) {
      this.msg = data;
    }   
  },
};

6. vuex

vue的状态管理器,可以集中式储存各组件之间的状态


// 该小节,我准备留在以后补充....

讲在最后

这篇文章从开头到结尾,虽然篇幅不多,但是完成度是比较坎坷的,原因是因为我的时间管理不够强,写着写着就又开始去学习其他的技术了(源码这种东西看多了,真的会上瘾),总是想着玉米西瓜一把抓,而忽略了一件事情从开始到闭环到重要性,希望总结于此,以后应当引以为戒。