看了就懂的vue组件通信

本文在具体实现上,主要是基于vue2.0并使用vue-cli脚手架搭建的一个基本项目,至于vue-cli这个脚手架,如果不懂也没关系,可以先用  ̄□ ̄||,主要介绍的是组件之间的通信。

0、前置

首先,肯定要有安装node和vue-cli了,具体怎么安装就不介绍了。

然后,创建一个初始化的项目vue_demo_2: vue init webpack vue_demo
这里写图片描述
生成的项目结构如下:
这里写图片描述
项目结构介绍:

| - build (运行文件夹,dev/prod运行时需要用到的相关文件,含webpack配置)
| - config (配置文件夹,比如说dev/prod两种对应的不同接口等设置)
| - dist (打包生成的部署文件夹,一开始没有的,跑命令npm run build之后可见!!!)
| - node_modules (一些安装的依赖模块)
| - src (项目代码)
  | - assets (资源文件夹,为了区分static,这里存自己的资源)
  | - components (页面文件夹,用来存放一些组件)
  | - router (路由文件夹)
  | - App.vue (vue主文件)
  | - main.js (入口文件,webpack配置的entrance)
| - static (资源文件夹,为了区分assets,这里存第三方的资源)
| - .babelrc (转码规则配置)
| - .editorconfig (代码规范配置)
| - .eslintignore (eslint检查忽略配置)
| - .eslintrc.js (eslint配置文件)
| - .gitignore (git忽略配置)
| - .postcssrc.js (postcss的load的config,文件里有对应的github地址)
| - index.html (html主页面)
| - package.json (项目的一些基本介绍,比如项目的描述、用到哪些模块等)
| - README.md

接下来,就可以正常实现不同组件之间的数据传递了,即组件之间的通信。

1、父组件向子组件传递数据

将App.vue这个组件中删除原来模板中的东西只保留基本的框架,当前App.vue文件内容如下:

<template>
  <div id="app">

  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>

<style>

</style>

src/components文件夹下,新建一个Child.vue单文件组件,创建props用于接收数据,并包含一个message属性,内容结构如下:

<template>
  <div class="child">
      <h2>我是子组件</h2>
      <p>这是我从父组件接收到的数据: {{cMessage}}</p>
  </div>
</template>

<script>
export default {
  name: 'Child',
  props:["cMessage"]
}
</script>

<style>
  .child{
    border:1px solid blue;
    width: 50%;
  }
</style>

App.vue组件,相当于是父组件中,引入子组件文件,并调用该子组件,然后将数据传递给子组件,修改后App.vue代码如下:

<template>
  <div id="app">
    <h1>我是父组件</h1>
    <child cMessage="hello child"></child> <!-- 调用子组件, 注意cMessage这个属性名称是由子组件中props定义 -->
  </div>
</template>

<script>
import Child from './components/Child.vue' // 引入子组件文件
export default {
  name: 'App',
  components:{
    Child // 声明子组件
  }
}
</script>

<style>
#app{
  width: 60%;
  border: 1px solid red;
}
</style>

npm run dev 在浏览器打开之后我们可以看到,父组件已经把数据传递给子组件了。
这里写图片描述
这是父组件向子组件传递的静态数据,当动态传递数据时,需要用到v-bind绑定数据,修改App.vue文件代码如下:

<template>
  <div id="app">
    <h1>我是父组件</h1>
    <!-- <child cMessage="hello child"></child> 调用子组件 -->
    <child v-bind:cMessage="pMessage"></child> <!-- 动态绑定父组件数据 ,cMessage还是子组件中props中的属性,pMessage是父组件的数据 -->
  </div>
</template>

<script>
import Child from './components/Child.vue' // 引入子组件文件
export default {
  name: 'App',
  components:{
    Child // 声明子组件
  },
  data(){
    return {
      pMessage:'hello child , 这是动态数据'
    }
  }
}
</script>

<style>
#app{
  width: 60%;
  border: 1px solid red;
}
</style>

结果如下:
这里写图片描述
以上就完全实现了父组件向子组件的通信了,总结:

第一步: 子组件在props中创建属性,用于接收父组件传递来的数据;

第二步:父组件先引入子组件文件,声明子组件,然后调用子组件,并在调用的子组件时,引用子组件props中声明的属性,将父组件数据赋值给该属性,就实现了父向子组件的数据传递,动态数据则是通过v-bind绑定父组件数据。

2、子组件向父组件传递数据

接着,继续实现子组件向父组件通信,修改Child.vue子组件文件,添加一个button 并给该按钮绑定了一个点击事件,在该点击事件方法中使用$emit()方法将数据传递给父组件,具体代码内容如下:

<template>
  <div class="child">
      <h2>我是子组件</h2>
      <p>这是我从父组件接收到的数据: {{cMessage}}</p>
      <button v-on:click="sendMessage">传数据给父组件</button>
  </div>
</template>

<script>
export default {
  name: 'Child',
  props:["cMessage"],
  methods:{
    sendMessage(){
      // 第一个参数:子组件触发的一个自定义事件, 第二个参数:子组件要向父组件传递的数据
      this.$emit('childEvent','hello parent , 这是从子组件传来的数据');
    }
  }
}
</script>

<style>
  .child{
    border:1px solid blue;
    width: 50%;
  }
</style>

App.vue这个父组件文件中,同样调用子组件,同时利用v-on监听子组件自定义的事件,并绑定自己本身实现的方法,具体代码修改内容如下:

<template>
  <div id="app">
    <h1>我是父组件</h1>
    <!-- <child message="hello child"></child> 调用子组件 -->
    <!-- <child v-bind:cMessage="pMessage"></child> 动态绑定父组件数据 -->
    <p>这是我从子组件接收到的数据:{{fromChild}}</p>
    <!-- 父组件触发的childEvent是子组件中方法sendMessage中$emit()的第一个参数自定义的事件名称,showMessage是父组件methods中的方法 -->
    <child v-bind:cMessage="pMessage" v-on:childEvent="showMessage"></child> 
  </div>
</template>

<script>
import Child from './components/Child' // 引入子组件文件
export default {
  name: 'App',
  components:{
    Child // 声明子组件
  },
  data(){
    return {
      pMessage:'hello child , 这是动态数据',
      fromChild:''
    }
  },
  methods:{
    showMessage(data){
      this.fromChild = data;
    }
  }
}
</script>

<style>
#app{
  width: 60%;
  border: 1px solid red;
}
</style>

在浏览器中,点击数据传递按钮,可以看到:
这里写图片描述
这样,也实现了子组件向父组件的数据传递,总结:

第一步: 子组件需要用$emit()触发一个自定义事件,事件名称即第一个参数名称,并将要传给父组件的数据作为$emit()的第二个参数。

第二步: 父组件同样需要引用子组件文件,声明子组件,然后调用子组件,在调用子组件时需要用v-on监听子组件中自定义的事件,绑定自身的方法,而该方法的参数就是子组件传递过来给父组件的数据。

3、组件之间的数据传递

在vue中,很多的一种情况就是组件之间并没有父子关系,就是很普通的两个组件,那么这种平级组件之间的通信是怎么的,在理解父子组件之间通信的基础上,我们接下来继续介绍它们的实现。

src/assets文件加下,新建一个mEvent.js文件,该js文件代码如下:

import Vue from 'vue'

export default new Vue

可以看到mEvent.js里面放的是一个空的Vue实例对象,事实上,通过父子组件之间相互通信父组件向子组件传递数据是借助porps,子组件向父组件通信则是借助$emit(),可以发现都需要一个中介,而平级组件之间的通信则是可以通过这个mEvent.js作为中介来实现。

src/componets文件夹下新建3个单文件组件:FirstComponent.vueSecondComponent.vueThirdComponent.vue,并在在App.vue这个组件中引用,此时App.vue中的代码为:

<template>
  <div id="app">
    <first-component></first-component>   <!-- 调用组件 -->
    <second-component></second-component>
    <third-component></third-component>
  </div>
</template>

<script>
import FirstComponent from './components/FirstComponent' // 引入单文件组件
import SecondComponent from './components/SecondComponent'
import ThirdComponent from './components/ThirdComponent'

export default{
  name:'App',
  components:{
    FirstComponent, // 声明组件
    SecondComponent,
    ThirdComponent
  }
}
</script>

<style>
#app{
  width: 80%;
  border: 1px solid black;
}
</style>

在第1个组件中,将数据传递给第3个组件,FirstComponent.vue具体代码如下:

<template>
    <div class="firstComponent">
        <h2>我是第1个组件</h2>
        <button v-on:click="oneSendToThird">向组件3传递数据</button>
    </div>
</template>

<script>
import mEvent from '../assets/mEvent.js' // 引入做问中介的单一事件
export default{
    name:'FirstComponent',
    methods:{
        oneSendToThird(){
            mEvent.$emit('firstComponentMessage','hello,这是来自第1个组件的数据');
        }
    }
}
</script>

<style>
.firstComponent{
    width: 60%;
    border: 1px solid red;
}
</style>

同样,在第2个组件中也将数据传递给第3个组件,SecondComponent.vue具体实现如下:

<template>
    <div class="secondComponent">
        <h2>我是第2个组件</h2>
        <button v-on:click="twoSendToThird">向组件3传递数据</button>
    </div>
</template>

<script>
import mEvent from '../assets/mEvent.js' // 引入做问中介的单一事件
export default{
    name:'SecondComponent',
    methods:{
        twoSendToThird(){
            mEvent.$emit('secondComponentMessage','hi,这是来自第2个组件的数据');
        }
    }
}
</script>

<style>
.secondComponent{
    width: 60%;
    border: 1px solid green;
}
</style>

此时,第3个组件要接收来自第1和第2个组件传递过来的数据,ThirdComponent.vue具体实现如下:

<template>
    <div class="thirdComponent">
        <h2>我是第3个组件</h2>
        <p>这是从第1个组件发过来的数据:{{msg1}}</p>
        <p>这是从第2个组件发过来的数据:{{msg2}}</p>
    </div>
</template>

<script>
import mEvent from '../assets/mEvent.js' // 引入做问中介的单一事件
export default{
    name:'ThirdComponent',
    data(){
        return{
            msg1:'',
            msg2:''
        }
    },
    mounted() {
         /*要借用es6的箭头函数,如果不用箭头函数
            在触发$on()事件前先:_this=this; 然后在普通函数中将数据赋值:_this.msg = data1;
            如果事先不暂存this,则会由于this的问题无法将数据添加
        */
        mEvent.$on('firstComponentMessage', (data1)=> {
            this.msg1 = data1;  
        })
         mEvent.$on('secondComponentMessage', (data2)=> {
            this.msg2 = data2;
        })
    },
}
</script>

<style>
.thirdComponent{
    width: 60%;
    border: 1px solid green;
}
</style>

那么在浏览器,分别点击按钮,可以看到数据已经传送成功了。
这里写图片描述
从代码实现来看,不难发现平级组件之间数据的通信主要通过借助一个中介mEvent.js,其实就是一个空的Vue实例对象,然后在利用$emit()发数据,$on()接数据,所以总结一下就是:

第一步:创建一个单一的事件中心来管理组件之间的通信,事实上就是一个中介;

第二步:在需要传值的组件中$emit()触发一个自定义事件,并传递参数;

第三步:在需要接收数据的组件中$on()监听自定义事件,并在回调函数中处理传递过来的参数。

至此,父子组件之间和不同组件之间的通信就已经完全实现了。

4、非vue-cli项目中组件之间的通信示例

其实本文主要介绍的就是利用vue-cli搭建一个初始化项目,然后实现单文件组件之间的通信,但是考虑到有些情况下,可能并没有用到vue-cli,所以还是决定实现一下非单文件组件通信实现的写法。

4.1 父组件向子组件传递数据

在电脑任意文件夹下,新建一个componet_comunication1.html,然后用在该文件中引入vue.js(2.0版本),实现父组件向子组件传递数据,具体代码如下:

<html>
    <head>
        <meta charset="utf-8">
        <title>父组件向子组件传递数据</title>
    </head>

    <style>
        #app{
            width: 50%;
            border: 1px solid red;
        }
        .child{
            width: 60%;
            border:1px solid blue;
        }
    </style>

    <body>

        <div id="app">
            <h2>我是父组件</h2>
            <child :msg="message"></child>
        </div>

        <template id="child">
            <div class="child">
                <h2>我是子组件</h2>
                <p>这是父组件传递过来的数据:{{msg}}</p>
            </div>
        </template>

    </body>

    <script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.js"></script> <!-- 单独引入vue文件 -->
    <script>
        window.onload = function () {
            new Vue({
                el:'#app',
                data:{
                    message:'hello child, 这是父组件的数据'
                },
                components:{ // 注册一个子组件
                    'child':{
                        props:['msg'],
                        template:'#child'
                    }
                }
            })
        }
    </script>

</html>

结果展示:
这里写图片描述
由于文章前面已经具体介绍过父组件如何向子组件传递数据的,所以就不再相信介绍了,只给出具体的实现demo。

4.2 平级组件之间数据传递

那么,平级组件之间传递数据componet_comunication_2.html代码实现如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>平级组件数据通信</title>
</head>

<body>
    <div id="box">
        <com-a></com-a>
        <com-b></com-b>
        <com-c></com-c>
    </div>
</body>

<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.js"></script> 
<script>
    var Event=new Vue(); //准备一个空的实例对象
    var A={ // 组件A
        template:`
            <div>
                <span>我是A组件</span> -> {{a}}
                <input type="button" value="把A数据给C" @click="send">
            </div>
        `,
        methods:{
            send(){
                Event.$emit('a-msg',this.a);
            }
        },
        data(){
            return {
                a:'我是a数据'
            }
        }
    };
    var B={ // 组件B
        template:`
            <div>
                <span>我是B组件</span> -> {{a}}
                <input type="button" value="把B数据给C" @click="send">
            </div>
        `,
        methods:{
            send(){
                Event.$emit('b-msg',this.a);
            }
        },
        data(){
            return {
                a:'我是b数据'
            }
        }
    };
    var C={ // 组件C
        template:`
            <div>
                <h3>我是C组件</h3>
                <span>接收过来的A的数据为: {{a}}</span>
                <br>
                <span>接收过来的B的数据为: {{b}}</span>
            </div>
        `,
        data(){
            return {
                a:'',
                b:''
            }
        },
        mounted(){
            Event.$on('a-msg',function(a){  //接收A组件的数据
                this.a=a;
            }.bind(this));
            Event.$on('b-msg',function(a){  //接收B组件的数据
                this.b=a;
            }.bind(this));
        }
    };
    window.onload=function(){
        new Vue({
            el:'#box',
            components:{
                'com-a':A,
                'com-b':B,
                'com-c':C
            }
        });
    };
</script>
</html>

结果展示:
这里写图片描述

好了,简单易懂的vue组件通信介绍就到这,后续有遇到的更多知识会慢慢补充的。如果不足或者不对的地方,欢迎各位指出~

每天总结一点点,每天进步一点点(^-^)V

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

英子的搬砖日志

您的鼓励是我创作的动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值