在上一篇博客vue学习笔记(八)组件校验&通讯中,咱们学会了vue中组件的校验和父组件向子组件传递信息以及子组件通知父组件(父子组件通讯),上一篇博客也提到那是对组件内容的刚刚开始,而本章博客将会重点的讲解vue-cli中的组件通讯,毕竟这在之后的开发内容中是很是广泛使用的。那么一块儿来看看本篇博客须要学习的知识点吧!javascript
学会使用vue-cli中父组件向子组件传递信息html
学会使用vue-cli中子组件向父组件传递信息vue
学会使用vue-cli中非父子组件传递信息java
既然提到要使用vue-cli实现组件通讯,那么确定要有vue-cli的环境,没有搭建vue-cli环境的园友能够参考这篇博客使用webstorm搭建vue-cli项目,这篇博客讲解的很是透彻,你们能够先将环境搭建好,而后再来看这篇博客,假设咱们项目搭建好了,项目目录结构以下jquery
咱们须要在src/components/parent/建立两个组件ParentComponent.vue和ChildComponent.vue,建立好以后目录以下web
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实现父组件向子组件传递信息我就讲解完了,接下来实现子组件向父组件传递信息。
学会了父组件向子组件传递信息,接下来就要学习子组件向父组件传递信息,一样咱们仍是使用如上的两个组件,更新以后的代码
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方法以后就能够接收到子组件传递过来的消息了
结果:
讲到这里父组件向子组件传递信息和子组件向父组件传递消息就所有讲解完了,能够说是讲解的很是详细,每一步我写的都是很是清楚
总结:
在组件通讯中除了有父组件向子组件传递信息和子组件向父组件传递信息,还有非父子组件通讯,一样我也会讲解的很是详细。
在src/components新建other目录和两个组件分别:BrotherComponent.vue,SisterComponent.vue,以及在src/assets下建立一个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 } ] })
结果
总结:
讲到这里组件基本通讯方式的已经讲解完成了,以后等学习了更高级的内容以后再补充新的组件通讯的方式,一共讲解了三种通讯方式,分别是父组件向子组件传递信息,子组件向父组件传递信息,非父子组件传递信息。内容很少讲解的也十分详细,那么为了巩固组件的知识下面也会讲解一些示例。
这个版本的任务清单在上一篇博客中已经讲解过了,为何在这里又要从新提到呢?博主以为上一篇博客没有讲解的很详细,并且本篇博客也是还有其它版本的任务清单,因此将这两个结合起来,学习起来也比较方便。
<!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>
步骤分析:
普通版的任务清单咱们就结束了,接下来须要实现的是vue-cli中的任务清单,这个任务清单和普通版的没有多大区别,只不过是换了一种写法,原理仍是没有改变的(换汤不换药),那么跟随我一块儿来瞧瞧吧!
在src/components下新建taks目录和ParentComponent.vue和ChildComponent.vue两个组件,创建以后的目录以下
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>
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>
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>
结果
思路分析:
vue-cli版的蜀国交税的话,咱们一样按照步骤进行,一步一步来解析
在src/components新建money目录和UnitTotalComponent.vue,UnitComponentA.vue,UnitComponentB.vue,UnitComponentC.vue,UnitComponentD.vue,UnitComponentE.vue六个组件,目录结构以下
在这里咱们将组件拆分了,上面是复制一样的组件,而这里是一个文件对应一个组件
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>
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>
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>
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>
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>
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>
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项目的格式进行讲解其它的知识点。
原文出处:https://www.cnblogs.com/jjgw/p/11964361.html