您的位置:首页 > Web前端 > Vue.js

Vue系列十七:组件间通信

2019-05-18 17:11 411 查看

组件间通信
1、组件间通信基本原则:
(1)、不要在子组件中直接修改父组件的状态数据
(2)、数据在哪, 更新数据的行为(函数)就应该定义在哪
2、vue 组件间通信的五种方式:
(1)、props
(2)、自定义事件
(3)、消息订阅与发布
(4)、slot
(5)、vuex
组件间通信方式一:props
1、在父组件传递属性

<List name='tom' :age='3' :set-name='setName'></List >

2、 在子组件内接收所有的属性
(1)、方式一: 只指定名称

props:['name','age','setName']

(2)、方式二: 指定名称和类型

props:{
name:String,
age:Number,
setNmae:Function
}

(3)、方式三: 指定名称、类型、必要性和默认值

props:{
name:{type:String,required:true,default:xxx},
}

注意:

  1. 此方式用于父组件向子组件传递数据
  2. 所有标签属性都会成为组件对象的属性, 模板页面可以直接引用
  3. 问题:
    a. 如果需要向非子后代传递数据必须多层逐层传递
    b. 兄弟组件间也不能直接 props 通信, 必须借助父组件才可以

案例:
在父组件App.vue中传递属性

<Item :comment="comment" :deleteComment="deleteComment" :index="index"/>
<List :comments="comments" :deleteComment="deleteComment"/>
<Add :addComment="addComment"/>

在子组件List.vue中接收属性

//声明接收属性:这个属性就会成为组件对象的属性
props: ['comments','deleteComment'],//只是指定属性名

在子组件Item.vue中接收属性

props: {//指定属性名和属性值的类型
comment: Object,
deleteComment: Function,
index: Number
}

在子组件Add.vue中接收属性

props:{
addComment:{//指定属性名、属性值的类型、必要性
type: Function,
required: true
}
}

组件间通信方式二:自定义事件
1、绑定事件监听
方式一: 通过 v-on 绑定

@delete_todo="deleteTodo"

方式二: 通过$on()

this.$refs.xxx.$on('delete_todo',function(todo){
this.deleteTodo(todo)
})

2、 触发事件

this.$emit(eventName,data)

注意:

  1. 此方式只用于子组件向父组件发送消息(数据)
  2. 问题:隔代组件或兄弟组件间通信此种方式不合适

案例:
在父组件App.vue中绑定事件监听

<!--给TodoHeader标签对象绑定addTodo事件监听-->
<TodoHeader @addTodo="addTodo"/>

在子组件TodoHeader.vue中触发事件

methods:{
addItem(){
//触发自定义事件:addTodo
this.$emit('addTodo',todo)
}
}

组件间通信方式三:消息订阅与发布
下载PubSubJS:

npm install --save pubsub-js

1、订阅消息

PubSub.subscribe('msg',function(msg,data){
})

2、发布消息

PubSub.publish('msg',data)

注意
 优点: 此方式可实现任意关系组件间通信(数据)

案例:
在父组件App.vue中订阅消息

import PubSub from 'pubsub-js'

mounted(){
//订阅消息
PubSub.subscribe('deleteTodo', (msg,index) =>{
this.deleteTodo(index)
})
}

在子组件TodoItem.vue中发布消息

import PubSub from 'pubsub-js'

methods:{
deleteItem(){
const {todo,index} = this
if(window.confirm(`确认删除${todo.title}吗?`)){
//发布消息
PubSub.publish('deleteTodo',index)
}
}
}

组件间通信方式四:slot
此方式用于父组件向子组件传递

标签数据

1、子组件:Child.vue

<template>
<div>
<slot name="xxx">不确定的标签结构</slot>
<div>组件确定的标签结构</div>
<slot name="yyy">不确定的标签结构</slot>
</div>
</template>

2、父组件:Parent.vue

<child>
<div slot="xxx">xxx对应的标签结构</div>
<div slot="yyy">yyyy对应的标签结构</div>
</child>

主要用于某一标签被反复使用时,可以使用slot插槽

案例:
在父组件App.vue中定义slot插槽

<todo-footer>
<input type="checkbox" v-model="isAllCheck" slot="checkAll"/>
<span slot="count">已完成{{completeSize}} / 全部{{todos.length}}</span>
<button class="btn btn-danger" v-show="completeSize" @click="deleteCompleteTodos" slot="delete">清除已完成任务</button>
</todo-footer>

在子组件TodoFooter.vue中使用slot插槽

<slot name="checkAll"></slot>
<slot name="count"></slot>
<slot name="delete"></slot>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: