浅谈Vue组件之间通信的五种方式

为什么需要使用组件通信?

组件是一个孤岛,所有的组件都无法直接访问其他组件的data,methods,computed,也就说每个组件都是一个局部作用域,这样做的目的是为了保护私有变量,保证每个组件之间的data不会相互影响.
但是在vue中我们经常需要在组件之间进行通信,下面我就来说说组件之间的几种通信方式:

父子组件之间通信原理大致就是如图所示:
浅谈Vue组件之间通信的五种方式_第1张图片

1.父传子

父传子我们一般通过动态绑定属性的方式获取,即在子组件标签上绑定属性,然后在子组件中用props来接收.

<body>
  <!-- 父组件 -->
  <div id="app">
    <!-- 子组件 -->
    <child mytitle="home" :mytext="text" :myshow='true'></child> 
  </div>
</body>
</html>
<script>
  // 全局组测的子组件
  Vue.component("child",{
    template:`
            
我是导航栏--{{mytitle}}--{{mytext}}
`
, // props:["mytitle","mytext","myshow"],数组方式接收 props:{ //对象方式接收,可以定义接收的数据类型 mytitle:String, mytext:String, myshow:Boolean } }) var vm=new Vue({ el:"#app", data:{ text:"我是在父组件中定义的", } }) </script>
2.子传父

子传父通过事件绑定的方式进行传递: 在子组件标签上绑定事件,在子组件中用this.$ emit来触发事件执行函数,并且可以传递参数即this.$ emit(“事件”,参数),函数在父组件中执行后就可以得到传递过来的参数.

<body>
  <!-- 父组件 -->
  <div id="app">
    <!-- 子组件 -->
    <!-- 在子组件上绑定两个事件event1和event2 -->
    <!-- 事件后面的函数如果加括号的话,参数要写成$event才能接收到,
    不加括号的话默认能接收到,推荐不加括号 -->
    <my-child @event1="handleEvent1($event)" @event2="handleEvent2">
    </my-child>
  </div>
</body>
</html>
<script>
  Vue.component("myChild",{
    template:`
    
child-
`
, data(){ return { text:"child定义的状态" } }, methods:{ handleClick(){ // 子组件中通过this.$emit来触发绑定的事件并进行传参 this.$emit("event1",1000000000) this.$emit("event2",this.text) } } }) var vm=new Vue({ el:"#app", methods:{ // 事件被触发执行后,函数会收到子组件传过来的参数 handleEvent1(data){ console.log("收到钱了--1",data) // 收到钱了--1 1000000000 }, handleEvent2(data){ console.log("收到了--2",data) // 收到了--2 child定义的状态 } } }) </script>
3.通过给组件绑定ref属性来进行通信

ref绑定在组件上,可以通过this.refs拿到组件对象. ref绑定在dom节点上,通过this.refs拿到的是原生dom节点.
但是这种方式太过暴力,暴露了vue并不是严格的MVVM模式,所有组件都可以随意修改拿到后的数据,所以不推荐使用.

<body>
  <div id="app">
    <!-- 绑定在标签上 -->
    <input type="text" ref="mytext">
    <button @click="handleClick()">Click</button>
    <!-- 绑定在组件上 -->
    <child1 ref="mychild"></child1>
  </div>
  
</body>
</html>
<script>
  Vue.component("child1",{
    template:`
    
{{name}}
`
, data(){ return { name:"Stephen--child1定义的" } } }) var vm=new Vue({ el:"#app", data:{ }, methods:{ handleClick(){ console.log(this.$refs.mytext.value) //可以拿到输入框的值 console.log(this.$refs.mychild.name) // (Stephen--child1定义的) this.$refs.mychild.name="Kerwin" //可以随意修改 console.log(this.$refs.mychild.name) //kerwin } } }) </script>
4.中央事件总线

中央事件总线通信原理图:
浅谈Vue组件之间通信的五种方式_第2张图片

中央事件总线通过重新new一个vue实例Bus,需要传递数据的组件可以通过bus.$ emit将数据传输给Bus,需要接收数据的组件则通过bus.$ on来接收传给Bus的数据.即this.$ emit(‘事件名’,参数)传送, this.$on(‘事件名’,(data)=>{})接收,bus通信一般用在非父子组件之间进行通信,比如下面例子中的child1hechild2兄弟组件之间.

<script>
  var bus = new Vue() //中央事件总线 bus.$on接收,bus.$emit传送
  // 组件1
  Vue.component("child1", {
    template: `
          
child1-
`
, methods: { handleClick() { bus.$emit("kerwinevent", "来自child1的问候") //将组件1里面的参数 //通过事件kerwinevent //以bus.$emit的方式传送给bus中央事件总线 } }, }) // 组件2 Vue.component("child2", { template: `
child2 {{str}}
`
, data() { return { str: "" } }, mounted() { bus.$on("kerwinevent", (data) => { //组件2中通过bus.$on的方式 //从bus中央事件总线上接收对应事件kerwinevent的数据 this.str = data //"来自child1的问候" }) } }) var vm = new Vue({ el: "#app", }) </script>
5.状态管理 Vuex

在大型组件开发项目中,通信会变得越来越频繁,不同组件之间的关系变得越来越复杂,异步请求的数据需要重复使用,这时候我们就需要用到vuex了.

首先vuex是什么?

官方定义:Vuex是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.
我的理解:也就是说在项目中我们需要共享的状态,不同页面(组件)之间需要共享的ajax请求数据,都可以存到vuex中,然后以一定的规则进行存储和拿取.

vuex的状态管理模式:
浅谈Vue组件之间通信的五种方式_第3张图片

  1. state:单一状态树 ,每个应用将仅仅包含一个 store 实例。
  2. getters:可以从store 中的state 中派生出一些状态,getters的返回值会根 据 它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。可以认为是store 的计算属性
  3. mutations:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
  4. actions: Action 提交的是 mutation,而不是直接变更状态。 Action 可
    以包含任意异步操作。

什么情况下我应该使用 Vuex?
Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。

结尾:以上就是我对vuex中组件间的通信技术的总结,不足的地方望补充(逆战班).

你可能感兴趣的:(浅谈Vue组件之间通信的五种方式)