vue学习笔记(九)vue-cli中的组件通讯

前言

在上一篇博客vue学习笔记(八)组件校验&通讯中,咱们学会了vue中组件的校验和父组件向子组件传递信息以及子组件通知父组件(父子组件通讯),上一篇博客也提到那是对组件内容的刚刚开始,而本章博客将会重点的讲解vue-cli中的组件通讯,毕竟这在之后的开发内容中是很是广泛使用的。那么一块儿来看看本篇博客须要学习的知识点吧!javascript

本章目标

  • 学会使用vue-cli中父组件向子组件传递信息html

  • 学会使用vue-cli中子组件向父组件传递信息vue

  • 学会使用vue-cli中非父子组件传递信息java

vue-cli中的父组件向子组件传递信息

既然提到要使用vue-cli实现组件通讯,那么确定要有vue-cli的环境,没有搭建vue-cli环境的园友能够参考这篇博客使用webstorm搭建vue-cli项目,这篇博客讲解的很是透彻,你们能够现将环境搭建好,而后再来看这篇博客,假设咱们项目搭建好了,项目目录结构以下jquery

(1)建立两个组件父组件和子组件

咱们须要在src/components/parent/建立两个组件ParentComponent.vue和ChildComponent.vue,建立好以后目录以下web

(2)分别在对应的组件中编写代码

ParentComponent.vuevue-router

<template>
    <div>
      <h1>{{title}}</h1>
      <!--注意:每一个组件注册必须有一个根元素-->
      <Child :message="message"></Child>
    </div>
</template>

<script>
  import Child from './ChildComponent'
    export default {
        name: "ParentComponent",
        data() {
          return {
            title:'这是父组件',
            message: '我是父组件'
          }
        },
        components:{
          Child
        }
    }
</script>

<style scoped>

</style>

首先在父组件中定义两个数据title和message,message是要传递給子组件的信息,第二步导入子组件和注册子组件,第三步将须要传递的信息绑定到组件上。vue-cli

总结app

  • 定义数据
  • 导入组件和注册组件
  • 数据绑定到组件上

ChildComponent.vuewebstorm

<template>
    <div>
      <!--注意每一个组件注册必须有一个根元素-->
      <h1>{{title}}</h1>
      <span>父组件传递过来的消息是:{{message}}</span>
    </div>
</template>

<script>
    export default {
      name: "ChildComponent",
      props:['message'],  //使用props接收父组件传递的信息
      data(){
          return{
            title:'这是子组件',

          }
      }
    }
</script>

<style scoped>

</style>

在子组件中咱们使用props来接收父组件传递过来的信息,而后进行渲染数据就能够了。

index.vue

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Hi from '@/components/Test/Hi'
import parent from '@/components/parent/ParentComponent'
Vue.use(Router)

export default new Router({
  routes: [
    {
      path:'/',
      component:parent,
      name:parent
    }
  ]
})

结果:

讲到这里使用vue-cli实现父组件向子组件传递信息我就讲解完了,接下来实现子组件向父组件传递信息。

vue-cli中的子组件向父组件传递信息

学会了父组件向子组件传递信息,接下来就要学习子组件向父组件传递信息,一样咱们仍是使用如上的两个组件,更新以后的代码

ParentComponent.vue

<template>
    <div>
      <h1>{{title}}</h1>
      <!--注意:每一个组件注册必须有一个根元素-->
      <Child :message="message" @send="getChildMsg"></Child>
      <h1>来自子组件的消息:{{childMsg}}</h1>
    </div>
</template>

<script>
  import Child from './ChildComponent'
    export default {
        name: "ParentComponent",
        data() {
          return {
            title:'这是父组件',
            message: '我是父组件',
            childMsg:''
          }
        },
        components:{
          Child
        },
        methods:{
          getChildMsg(data){
            this.childMsg=data;
          }
        }
    }
</script>

<style scoped>

</style>

父组件中咱们从新定义了一个新的属性(childMsg)来接收子组件传递过来的消息,能够知道子组件向父组件传递的事件是send,而后调用send来接收子组件传递过来的数据

ChildComponent.vue

<template>
    <div>
      <!--注意每一个组件注册必须有一个根元素-->
      <h1>{{title}}</h1>
      <span>父组件传递过来的消息是:{{message}}</span>
      <input type="button" value="向父组件传递信息" @click="sendMsgToParent">
    </div>
</template>

<script>
    export default {
      name: "ChildComponent",
      props:['message'],  //使用props接收父组件传递的信息
      data(){
          return{
            title:'这是子组件',
            fromChildMsg:'我是来自子组件的消息',
          }
      },
      methods:{
        sendMsgToParent(){
          this.$emit('send',this.fromChildMsg);
        }
      }
    }
</script>

<style scoped>

</style>

子组件中也是从新定义了一个新的属性(fromChildMsg),这个属性是须要传递给父组件的,而后经过按钮的点击事件使用this.$emit()将事件名称和数据传递给父组件,父组件注册send方法以后就能够接收到子组件传递过来的消息了

结果:

讲到这里父组件向子组件传递信息和子组件向父组件传递消息就所有讲解完了,能够说是讲解的很是详细,每一步我写的都是很是清楚

总结:

  • 父组件向子组件传递信息经过props
  • 子组件向父组件传递信息经过this.$emit(‘事件名称’,值1,值2,....)

vue-cli中的非父子组件传递信息

在组件通讯中除了有父组件向子组件传递信息和子组件向父组件传递信息,还有非父子组件通讯,一样我也会讲解的很是详细。

(1)新建目录用于非父子组件通讯

在src/components新建other目录和两个组件分别:BrotherComponent.vue,SisterComponent.vue,以及在src/assets下建立一个event.js文件,建立以后的目录以下

(2)event.js充当总线

event.js这个文件中咱们只建立了一个新的Vue实例,之后它就承担起了组件之间通讯的用来充当总线桥梁了,也就是中央事件总线,为的就是将BrotherComponent.vue和SisterComponent.vue联系起来。

event.js

//方式一
import Vue from 'Vue'
export  default  new Vue
/*方式二
let bus=new Vue
export  default  bus
*/

BrotherComponent.vue

<template>
  <div>
    <h1>兄弟组件</h1>
    <input type="button" @click="sendMsg" value="向姐妹组件传递信息">
    <sister></sister>
  </div>
</template>

<script>
    //导入总线
    import bus from '../../assets/event'
    //导入姐妹组件
    import sister from './SisterComponent'
    export default {
        name: "BrotherComponent",
      data(){
          return{
            tips:'I am your brother'
          }
      },
      components:{
          sister  //注册界面组件
      },
      methods:{
        sendMsg(){
          bus.$emit('send',this.tips);
        }
      }
    }
</script>

<style scoped>

</style>

在这个组件中首先是导入的总线和姐妹组件,而后注册了姐妹组件,咱们在响应点击事件的sendMsg函数中用$emit触发了一个自定义的send事件,并传递了一个字符串参数,

这个参数就是须要传递个姐妹组件的值。$emit实例方法触发当前实例(这里的当前实例就是bus)上的事件,附加参数都会传给监听器回调

SisterComponent.vue

<template>
  <div>
    <h1>姐妹组件</h1>
    <span>{{msg}}</span>
  </div>
</template>

<script>
  import bus from '../../assets/event'
    export default {
        name: "SisterComponent",
      data(){
          return{
            msg:''
          }
      },
      methods:{
        getMsg(){
          bus.$on('send',data=>{
            this.msg=data;
          })
        }
      },
      mounted(){
          this.getMsg();
      }
    }
</script>

<style scoped>

</style>

在这个组件中,咱们在mounted中,监听了send,并把传递过来的字符串参数传递给了$on监听器的回调函数,mounted:是一个Vue生命周期中的钩子函数,简单点说就相似于jquery的ready,Vue会在文档加载完毕后调用mounted函数,$on:监听当前实例上的自定义事件(此处当前实例为bus)。事件能够由$emit触发,回调函数会接收全部传入事件触发函数($emit)的额外参数

index.js

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Hi from '@/components/Test/Hi'
import parent from '@/components/parent/ParentComponent'
import brother from '@/components/other/BrotherComponent'
Vue.use(Router)

export default new Router({
  routes: [
    {
      path:'/',
      component:brother,
      name:brother
    }
  ]
})

结果

总结:

  • 建立一个事件总线,例如示例中event.js,用它做为通讯桥梁
  • 在须要传值的组件中用bus.$emit触发一个自定义事件,并传递参数
  • 在须要接收数据的组件中用bus.$on监听自定义事件,并在回调函数中处理传递过来的参数

讲到这里组件基本通讯方式的已经讲解完成了,以后等学习了更高级的内容以后再补充新的组件通讯的方式,一共讲解了三种通讯方式,分别是父组件向子组件传递信息,子组件向父组件传递信息,非父子组件传递信息。内容很少讲解的也十分详细,那么为了巩固组件的知识下面也会讲解一些示例。

综合练习

普通版任务清单

 这个版本的任务清单在上一篇博客中已经讲解过了,为何在这里又要从新提到呢?博主以为上一篇博客没有讲解的很详细,并且本篇博客也是还有其它版本的任务清单,因此将这两个结合起来,学习起来也比较方便。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>普通版任务清单</title>
    </head>
    <body>
        <div id="app">
            <input type="text"  v-model="newTask" @keyup.enter="addNew" placeholder="请输入你要完成的任务"/>
            <todo-item v-for="(item,index) of tasks" :title='item' :index="index" @remove="removeItem"></todo-item>
        </div>
        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            let vm=new Vue({
                el:'#app',
                data:{
                    newTask:'',
                    tasks:['看一场电影','读一本书','请朋友吃一顿饭'],
                },
                methods:{
                    addNew(){
                        this.tasks.unshift(this.newTask);//向任务清单的最前面添加任务
                        this.newTask='';    //清空文本框中的内容
                    },
                    removeItem(index){
                        if(confirm('你肯定要删除吗?')){
                            this.tasks.splice(index);
                        }
                    }
                },
                computed:{
                    
                },
                components:{
                    'todoItem':{
                        props:['title',"index"],
                        template:'<li><span>{{title}}</span><button @click="sendMsg(index)">X</button></li>',
                        methods:{
                            sendMsg(index){
                                console.log(index);
                                this.$emit('remove',index);
                            }
                        }
                    }
                }
                
            })
            
        </script>
    </body>
</html>

步骤分析:

  • 1.定义好要添加的任务(newTask)和所有的任务清单(tasks),按下enter键的时候向任务清单添加一条任务,
  • 2.定义好任务列表清单组件,而后将任务列表和索引传递进去
  • 3.定义好子组件通知父组件的事件this.$emite('remove',index)
  • 4.父组件接收到子组件通知的事件和下标索引,而后作出相应的处理

vue-cli版任务清单

普通版的任务清单咱们就结束了,接下来须要实现的是vue-cli中的任务清单,这个任务清单和普通版的没有多大区别,只不过是换了一种写法,原理仍是没有改变的(换汤不换药),那么跟随我一块儿来瞧瞧吧!

1.新建目录和组件

在src/components下新建taks目录和ParentComponent.vue和ChildComponent.vue两个组件,创建以后的目录以下

2.对应的组件中编写代码

ParentComponent.vue

<template>
  <div>
    <h1>这是父组件</h1>
    <input type="text" v-model="newTask" @keyup.enter="addNew" placeholder="请输入你要添加的任务">
    <child v-for="(item,index) of tasks" :item="item" :index="index" @remove="removeItem" :key="index"></child>
  </div>
</template>

<script>
    import Child from './ChildComponent'
    export default {
        name: "ParentComponent",
        components:{
          Child     //注册子组件
        },
      data(){
          return{
            newTask:'',
            tasks:['买一本书','看一场电影','写一篇博客'],
          }
      },
      methods:{
        addNew(){
          this.tasks.unshift(this.newTask);
          this.newTask="";
        },
        removeItem(index){  //删除任务
          if(confirm('你肯定要删除吗?')){
            this.tasks.splice(index);
          }
        }
      }
    }
</script>

<style scoped>

</style>
  • 父组件中首先导入子组件和注册子组件,而后定义要添加的任务清单(newTask)和所有的任务清单列表(tasks),输入框中addNew方法是当咱们按下enter键时向tasks添加一条新的任务清单。
  • 注册好子组件以后,将任务清单项和每一条任务清单项的索引传递给子组件。
  • 父组件接收子组件通知的方法(remove),而后对任务清单作出相应的处理。

ChildComponent.vue

<template>
    <div>
      <li>{{item}}<button @click="sendMsg(index)">X</button></li>
    </div>
</template>

<script>
    export default {
        name: "ChildComponent",
        props:['item','index'],
      data(){
          return{

          }
      },
      methods:{
        sendMsg(index){
            this.$emit('remove',index);
          }
      }
    }
</script>

<style scoped>

</style>
  • 在子组件中,首先使用props接收父组件传递过来的两个参数item,index。
  • 定义一个通知父组件的方法,告诉父组件须要删除那个任务清单。

index.js

import Vue from 'vue'
import Router from 'vue-router'
import  parent from '@/components/task/ParentComponent'
Vue.use(Router)

export default new Router({
  routes: [
    {
      path:'/',
      component:parent,
      name:parent
    }
  ]
})

vue-cli版本的任务清单咱们也就完成了,总之换汤不换药,仍是那句老话,父组件向子组件传递信息使用props,子组件向父组件传递信息使用this.$emit('事件名称',值1,值2,...)

普通版蜀国交税

这个案例和以前的也差很少,原理仍是同样的,那么一块儿来看看吧!

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>普通版蜀国交税</title>
    </head>
    <body>
        <div id="app">
            <h2>{{name}}</h2>
            <h3>总数:{{total}}</h3>
            <me-tax @tax="undateTotal" name="赵云" :unit="unit"></me-tax>
            <me-tax @tax="undateTotal" name="马超" :unit="unit"></me-tax>
            <me-tax @tax="undateTotal" name="张飞" :unit="unit"></me-tax>
            <me-tax @tax="undateTotal" name="关羽" :unit="unit"></me-tax>
            <me-tax @tax="undateTotal" name="黄忠" :unit="unit"></me-tax>
            <h3>{{msg}}</h3>
        </div>
        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            Vue.component('me-tax',{
                template:'<button @click="upTax">{{money}}</button>',
                data(){
                    return{
                        money:0,
                    }
                },
                props:['name','unit'],
                methods:{
                    upTax(){
                        this.money+=this.unit;    //税收总和
                        this.$emit('tax',{name:this.name,money:this.money});//    通知父组件
                    }
                }
            })
            let vm=new Vue({
                el:'#app',
                data:{
                    name:'蜀国交税',
                    total:0,
                    unit:10,    //每次交税的量
                    msg:''
                },
                methods:{
                    undateTotal(obj){
                        this.total+=this.unit;
                        this.msg=obj.name+"交税成功,已交税"+obj.money;
                    }
                },
                computed:{
                    
                }
                
            })
            
        </script>
    </body>
</html>

结果

思路分析:

  • 父组件中定义好交税的总和(total)和每次交税的数量(unit)
  • 定义好子组件,接收父组件传递过来的两个参数name和unit,定义一个计算本身交税的总量和通知父组件的方法tax
  • 父组件接收到子组件的通知以后,计算所交税的总和,并显示那位蜀将交的税收

vue-cli版蜀国交税

vue-cli版的蜀国交税的话,咱们一样按照步骤进行,一步一步来解析

(1)新建目录和定义六个组件

在src/components新建money目录和UnitTotalComponent.vue,UnitComponentA.vue,UnitComponentB.vue,UnitComponentC.vue,UnitComponentD.vue,UnitComponentE.vue六个组件,目录结构以下

 

在这里咱们将组件拆分了,上面是复制一样的组件,而这里是一个文件对应一个组件

(2)在对应的组件中编写代码

UnitTotalComponent.vue

<template>
  <div>
    <h1>{{name}}</h1>
    <h3>总交税:{{total}}</h3>
    <A title="张飞" :unit="unit" @tax="updateTotal"></A>
    <B title="关羽" :unit="unit" @tax="updateTotal"></B>
    <C title="马超" :unit="unit" @tax="updateTotal"></C>
    <D title="赵云" :unit="unit" @tax="updateTotal"></D>
    <E title="黄忠" :unit="unit" @tax="updateTotal"></E>
    <h3>{{msg}}</h3>
  </div>
</template>

<script>
  //导入相应的组件
  import A from './UnitComponentA'
  import B from './UnitComponentB'
  import C from './UnitComponentC'
  import D from './UnitComponentD'
  import E from './UnitComponentE'
    export default {
        name: "UnitTotalComponent",
        data(){
          return{
            name:'蜀国交税',
            total:0,
            unit:10,  //每次交税的量
            msg:''
          }
        },
      components:{  //注册组件
          A,
          B,
          C,
          D,
          E
      },
        methods:{
          updateTotal(obj){
            this.total+=this.unit;
            this.msg=obj.name+'交税成功,已交税'+obj.money;
          }
        }
    }
</script>

<style scoped>

</style>
  • UnitTotalComponent组件中首先导入了五个组件以及注册了这五个组件
  • 定义须要传递的数数据(每次交税的量unit)
  • 根据每一个子组件通知的方法将所交的税计算总和,并显示哪位蜀将

UnitComponentA.vue

<template>
    <div>
      <button @click="upTax">{{money}}</button>
    </div>
</template>

<script>
    export default {
        name: "UnitComponentA",
      props:['title','unit'],
      methods:{
        upTax(){
          this.money+=this.unit;
          this.$emit('tax',{name:this.title,money:this.money});

        }
      },
      data(){
          return{
            money:0,
          }
      }
    }
</script>

<style scoped>

</style>
  • UnitComponentA组件接收父组件传递过来的两个属性title和unit
  • 定义好通知父组件的方法tax,将参数和方法传过去

UnitComponentB.vue

<template>
  <div>
    <button @click="upTax">{{money}}</button>
  </div>
</template>

<script>
    export default {
      name: "UnitComponentB",
      props:['title','unit'],
      methods:{
        upTax(){
          this.money+=this.unit;
          this.$emit('tax',{name:this.title,money:this.money});

        }
      },
      data(){
        return{
          money:0,
        }
      }
    }
</script>

<style scoped>

</style>
  • UnitComponentB组件接收父组件传递过来的两个属性title和unit
  • 定义好通知父组件的方法tax,将参数和方法传过去

UnitComponentC.vue

<template>
  <div>
    <button @click="upTax">{{money}}</button>
  </div>
</template>

<script>
    export default {
        name: "UnitComponentC",
      props:['title','unit'],
      methods:{
        upTax(){
          this.money+=this.unit;
          this.$emit('tax',{name:this.title,money:this.money});

        }
      },
      data(){
        return{
          money:0,
        }
      }
    }
</script>

<style scoped>

</style>
  • UnitComponentC组件接收父组件传递过来的两个属性title和unit
  • 定义好通知父组件的方法tax,将参数和方法传过去

UnitComponentD.vue

<template>
  <div>
    <button @click="upTax">{{money}}</button>
  </div>
</template>

<script>
    export default {
        name: "UnitComponentD",
      props:['title','unit'],
      methods:{
        upTax(){
          this.money+=this.unit;
          this.$emit('tax',{name:this.title,money:this.money});

        }
      },
      data(){
        return{
          money:0,
        }
      }
    }
</script>

<style scoped>

</style>
  • UnitComponentD组件接收父组件传递过来的两个属性title和unit
  • 定义好通知父组件的方法tax,将参数和方法传过去

UnitComponentE.vue

<template>
  <div>
    <button @click="upTax">{{money}}</button>
  </div>
</template>

<script>
    export default {
        name: "UnitComponentE",
      props:['title','unit'],
      methods:{
        upTax(){
          this.money+=this.unit;
          this.$emit('tax',{name:this.title,money:this.money});

        }
      },
      data(){
        return{
          money:0,
        }
      }
    }
</script>

<style scoped>

</style>
  • UnitComponentE组件接收父组件传递过来的两个属性title和unit
  • 定义好通知父组件的方法tax,将参数和方法传过去

index.js

import Vue from 'vue'
import Router from 'vue-router'
import total from '@/components/money/UnitTotalComponent'
Vue.use(Router)

export default new Router({
  routes: [
    {
      path:'/',
      component:total,
      name:total
    }
  ]
})

结果

vue的组件通讯到这里就要告一段落了,该讲解的知识点也讲解完成了,反正这篇博客你反复去看总会有收获的。学习起来并不难,任务清单和蜀国交税这两个案例将所学的组件通讯结合了起来,学习起来也很是方便。

总结

本篇博客主要讲解了三个知识点,父组件向子组件传递信息,子组件向父组件传递信息,非父子组件通讯,父组件向子组件传递信息主要是经过props进行数据传递,子组件向父组件传递信息主要是经过this.$emit('事件名',值1,值2,...),非父子组件通讯,先创建中央通讯总线,传递数据的一方使用bus.$emit(),接收数据的一方使用bus.$on(),本篇博客已经将组件通讯这一方面的知识讲解的很是透彻,后期全部的博客几乎都会围绕vue-cli项目的格式进行讲解其它的知识点。

相关文章
相关标签/搜索