Vue-组件间通信
创建时间:
字数:2.6k
阅读:
组件间通信
- props 父组件向子组件传递数据
- $emit 自定义组件 ,子组件数据传递父组件
- slot 插槽分发内容
组件间通信规则
- 不要再子组件中修改父组件传递的数据
- 数据初始化时,应当看初始化的数据是否用于多个组件中, 如果需要被用于多个组件中, 则初始化在父组件中; 如果在一个组件中使用,则出现在该组件中
- 数据初始化在那个组件中, 更新就应当在那个组件中
声明组件对象中定义 props
- 在声明组件对象中使用props
1 2 3 4 5 6 7
| const MyComponet { template: '<div></div>', props: 此处有三种方式, components: { } }
|
方式一: 指定传递属性名, 数组形式
1
| props: ['id','name','slary','author']
|
方式二:指定传递数据对象和数据类型,对象像是
1 2 3 4 5 6 7 8 9
| props: { id: Number, name: String, salary: Number, isPublish: Boolean, commentIds: Array, author: Objects, getEmp: Function }
|
引用组件时动态赋值
在引用组件时通过v-bind动态赋值1 2 3
| <my-componet v-bind:id="2" :name="Xiaoxin" :slary="9999">
</my-componet>
|
实例一
AppHome.js1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| ;(function () { const template = ` <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <!--右边上半区域--> <h1 class="page-header">Dashboard</h1> <!--通过属性绑定的形式传递数据--> <dashboard :hobbies="hobbies"></dashboard> <!--右边下半区域--> <h2 class="sub-header">Section title</h2> <home-list :empList="empList"></home-list> </div>` window.AppHome = { template, data(){ return { hobbies:['eatting','sleep','gamming','coding'], empList: [ { id:1, name:'xiaoxin1', slary:4000 }, { id:2, name:'xiaoxin', slary:4000 }, { id:3, name:'xiaoxin2', slary:4000 }, { id:4, name:'xiaoxin3', slary:4000 }, ] } }, components: { Dashboard, homeList } } })()
|
dashboard.sh1 2 3 4 5 6 7 8 9 10 11 12 13
| ;(function () { window.Dashboard = { template: ` <div class="row placeholders"> <div v-for="hobby in hobbies" class="col-xs-6 col-sm-3 placeholder"> <img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" width="200" height="200" class="img-responsive" alt="Generic placeholder thumbnail"> <h4>{{ hobby }}</h4> <span class="text-muted"></span> </div> </div>`, props: ['hobbies'] } })()
|
传递数据注意
- props只适用于父组件向子组件传递
- 所有标签属性都会成为组件对象的属性, 模板页面可以直接饮用
- 如果需要向非子组件传递(孙代之后), 必须逐层传递
- 兄弟组件之间不能直接传递,必须通过父组件传递
实例二
子组件删除数据,根据传递数据使用原则,原数据定义在哪里就在那个组件中进行操作,所以这里删除的函数定义在了AppHome.js父组件中
AppHome.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| ;(function () { const template = ` <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <!--右边上半区域--> <h1 class="page-header">Dashboard</h1> <!--通过属性绑定的形式传递数据--> <dashboard :hobbies="hobbies"></dashboard> <!--右边下半区域--> <h2 class="sub-header">Section title</h2> <home-list :empList="empList" :delItem="delItem"></home-list> </div>` window.AppHome = { template, data(){ return { hobbies:['eatting','sleep','gamming','coding'], empList: [ { id:1, name:'xiaoxin1', slary:4000 }, { id:2, name:'xiaoxin', slary:4000 }, { id:3, name:'xiaoxin2', slary:4000 }, { id:4, name:'xiaoxin3', slary:4000 }, ] } }, components: { Dashboard, homeList }, methods: { delItem(inx) { this.empList.splice(inx, 1) } } } })()
|
homeList.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| ;(function () { const template = `<div class="table-responsive"> <table class="table table-striped"> <thead> <tr> <th>ID</th> <th>Name</th> <th>Salary</th> <th>Action</th> </tr> </thead> <emp-list v-for="emp,inx in empList" :emp="emp" :inx="inx" :delItem="delItem" :key="emp.id"></emp-list> <tbody> </tbody> </table> </div>` window.homeList = { template, components: { empList }, props: ['empList', 'delItem'] } })()
|
empList.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| ;(function () { const template = `<tr> <td>{{emp.id}}</td> <td>{{emp.name}}</td> <td>{{emp.slary}}</td> <td> <a href="#" @click="delEmp">删除</a> </td> </tr>` window.empList = { template, props: { emp: { type: Object, request: true }, inx: Number, delItem: Function }, methods: { delEmp(){ this.delItem(this.inx) } } } })()
|
自定义传递数据 $emit
$emit主要用于子组件传递数据到父组件
实例
AppHome.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| ;(function () { const template = ` <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <!--右边上半区域--> <h1 class="page-header">Dashboard</h1> <!--通过属性绑定的形式传递数据 @自定义监听事件 = 监听函数 在子组件dashboard中触发了del_hobby事件调用delHobby函数 --> <dashboard :hobbies="hobbies" @del_hobby="delHobby"></dashboard> <!--右边下半区域--> <h2 class="sub-header">Section title</h2> <home-list :empList="empList" :delItem="delItem"></home-list> </div>` window.AppHome = { template, data(){ return { hobbies:['eatting','sleep','gamming','coding'], empList: [ { id:1, name:'xiaoxin1', slary:4000 }, { id:2, name:'xiaoxin', slary:4000 }, { id:3, name:'xiaoxin2', slary:4000 }, { id:4, name:'xiaoxin3', slary:4000 }, ] } }, components: { Dashboard, homeList }, methods: { delItem(inx) { this.empList.splice(inx, 1) }, delHobby(inx) { this.hobbies.splice(inx, 1) } } } })()
|
dashboard.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| ;(function () { window.Dashboard = { template: ` <div class="row placeholders"> <div v-for="hobby,inx in hobbies" class="col-xs-6 col-sm-3 placeholder"> <img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" width="200" height="200" class="img-responsive" alt="Generic placeholder thumbnail"> <h4>{{ hobby }}</h4> <a href="#" @click="delHobby(inx)">del</a> </div> </div>`, props: ['hobbies','del_hobby'], methods: { delHobby(inx){ this.$emit('del_hobby', inx) } } } })()
|
注意事项
- 自定义事件只用于子组件想父组件传递数据
- 隔代组件或兄弟组件不适合这种方式
slot 插槽
实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| ;(function () { const template = ` <!--头部导航区域--> <!--必须要有一个根元素, 有且仅有一个,下面添加div标签--> <div> <app-navbar></app-navbar> <!--核心区域:分左右两边--> <div class="container-fluid"> <div class="row"> <!--左边菜单栏区域--> <app-left></app-left> <!--右边主页面区域: 分上下两个区域--> <app-home> <!--这里定义slot的名称为"dashboard",当子组件引用这个slot时就会被替换为对应的html标签--> <h1 slot="dashboard" class="page-header">{{title}}</h1> </app-home> </div> </div> </div>` window.App = { template, components: { AppNavbar, appLeft, AppHome, }, data(){ return { title: 'Dashboard01' } } } })()
|
AppHome.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| ;(function () { const template = ` <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <!--右边上半区域--> <!--<h1 class="page-header">Dashboard</h1>--> <!--这里引用父组件中定义的slot为"dashboard"的元素--> <slot name="dashboard"></slot> <!--通过属性绑定的形式传递数据 @自定义监听事件 = 监听函数 在子组件dashboard中触发了del_hobby事件调用delHobby函数 --> <dashboard :hobbies="hobbies" @del_hobby="delHobby"></dashboard> <!--右边下半区域--> <h2 class="sub-header">Section title</h2> <home-list :empList="empList" :delItem="delItem"></home-list> </div>` window.AppHome = { template, data(){ return { hobbies:['eatting','sleep','gamming','coding'], empList: [ { id:1, name:'xiaoxin1', slary:4000 }, { id:2, name:'xiaoxin', slary:4000 }, { id:3, name:'xiaoxin2', slary:4000 }, { id:4, name:'xiaoxin3', slary:4000 }, ] } }, components: { Dashboard, homeList }, methods: { delItem(inx) { this.empList.splice(inx, 1) }, delHobby(inx) { this.hobbies.splice(inx, 1) } } } })()
|
注意事项
- 只能用于父组件想子组件传递数据
- 传递的插槽标签需要定义在父组件中
非父子组件之间进行通信 PubSubJs
理解: 订阅消息 ==== 绑定事件监听, 发布消息 ==== 触发事件
注意: 需要先执行订阅事件subscribe, 然后才能publish时间
安装: npm install pubsub-js
订阅消息(绑定监听事件)
先在create钩子函数中订阅消息
注意这里要使用箭头函数”=>”,这样this就是代表父函数对象Vue,否则代表pubsubJs
1 2 3
| PubSub.subscribe('消息名称',(event, data) => {
})
|
发布消息(触发时间)
1
| PubSub.publish('消息名称',data)
|
实例
AppLeft.js(订阅方)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| ;(function () { window.appLeft = { template: `<div class="col-sm-3 col-md-2 sidebar"> <ul class="nav nav-sidebar"> <!--<li class="active"><a href="#">Overview <span class="sr-only">(current)</span></a></li>--> <li @click="currentActive(item)" :class="{active: current === item}" v-for="item in top"> <a :href="item.url">{{item.name}}<span>({{delNum}})</span></a> </li> </ul> </div>`, data(){ return { top:[ {name:'Overview',url:'#'}, {name:'Reports',url:'#'}, {name:'Analytics',url:'#'}, {name:'Export',url:'#'}, ], current: top[1], delNum:0, } }, methods:{ currentActive(item){ this.current = item } }, created() { PubSub.subscribe('changeNum',(event, num) => { this.delNum = this.delNum + num }) } } })()
|
AppHome.js(发布方)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| ;(function () { const template = ` <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <!--右边上半区域--> <!--<h1 class="page-header">Dashboard</h1>--> <!--这里引用父组件中定义的slot为"dashboard"的元素--> <slot name="dashboard"></slot> <!--通过属性绑定的形式传递数据 @自定义监听事件 = 监听函数 在子组件dashboard中触发了del_hobby事件调用delHobby函数 --> <dashboard :hobbies="hobbies" @del_hobby="delHobby"></dashboard> <!--右边下半区域--> <h2 class="sub-header">Section title</h2> <home-list :empList="empList" :delItem="delItem"></home-list> </div>` window.AppHome = { template, data(){ return { hobbies:['eatting','sleep','gamming','coding'], empList: [ { id:1, name:'xiaoxin1', slary:4000 }, { id:2, name:'xiaoxin', slary:4000 }, { id:3, name:'xiaoxin2', slary:4000 }, { id:4, name:'xiaoxin3', slary:4000 }, ] } }, components: { Dashboard, homeList }, methods: { delItem(inx) { this.empList.splice(inx, 1) }, delHobby(inx) { this.hobbies.splice(inx, 1) PubSub.publish('changeNum', 1) } } } })()
|
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 jaytp@qq.com