关于Vue组件之间通信的n种方式(全)
1. 父组件向子组件传值(poops)
2. 子组件向父组件传值($emit)
3. 兄弟组件之间传值(eventBus)
4. 父组件操作子组件的实例(ref)
5. $parent 和 $children
6. 跨层级通信provide/inject
7. $attrs 和 $listeners
8. localStorage/sessionStorage
9. Vuex
10.v-model
我是用vue脚手架创建的项目,项目设计目录结构如下:
APP.vue包含三个子组件(children)
children各自包含自己的一个子组件(GrandSon)
- 父组件向子组件传值(poops)最常见
APP.vue代码:
<ChildrenOne v-bind:value="value"></ChildrenOne>
ChildrenOne代码:
// 接收父组件传递过来的值
props: ['value']
使用父组件传递过来的value值:
<span>这是父组件APP.vue歘递过来给我的=------{{value}}</span>
2: 子组件向父组件传值($emit)
childrenOne代码:
<button @click="handleClick">点击按钮给我父亲发点消息</button>
// .....................省略
handleClick () {
// 点击按钮触发事件给父亲发消息
this.$emit('forMyFather', 'I am your daugther')
},
App.vue里面进行监听子组件childreOne触发的事件,监听的名字和子组件$emit函数的第一个参数同:
<ChildrenOne v-bind:value="value" @forMyFather="handleClick"></ChildrenOne>
// .........................省略
// 这里直接用父组件在data中定义的变量接收就可以使用了
handleClick (value) {
this.fromMyDaugther = value
console.log(value)
}
3:兄弟组件之间传值(eventBus)
简要说明:兄弟组件之间需要中间人帮助传值,就是事件总线
事件总线通常是Vue的实例
3.1为了方便直接挂载到Vue原型prototype上面
main.js代码:
// 往后使用可以用this.$bus触发或者监听事件
Vue.prototype.$bus = new Vue()
3.2Chilren1中代码:
<button @click="handleClickOne">给我姐姐发点消息</button>
// ............................省略
// msg定义为一个对象,当触发事件是是可以传递多个值的。,只要放在对象里就可以
data () {
return {
msg: {
msg1: 'to My young Sister',
msg2: 'you so smart'
}
}
}
// ............................省略
handleClickOne () {
var msg = this.msg
// 用挂载在Vue原型上面的$bus充当事件总线发送
this.$bus.$emit('forMySister', { msg })
console.log(msg)
}
3.3Children2中相关代码:
mounted () {
this.$bus.$on('forMySister', msg => {
// Object.values是可以遍历对象拿到对应值组成的数组的,下列操作就是为了把msg中第一项对应的值拿出来
this.fromMyYoungSister = Object.values(Object.values(msg)[0])[0] + ' ' + Object.values(Object.values(msg)[0])[1]
console.log(this.fromMyYoungSister)
})
}
// 使用
<h3>这是我妹妹给我传递的消息----{{fromMyYoungSister}}</h3>
4:父组件操作子组件的实例(ref)
可以操作属性和方法(数据是响应式的)
Children2代码:
<!-- 第四种方式:给子组件添加ref属性,让父组件可以获取子组件的所有属性 -->
<GrandSonTwo ref='forMyFather'></GrandSonTwo>
// 操作子实例
mounted () {
console.log(this.$refs)
// this.$refs.forMyFather.msg = 'kk'
this.fromMyChildren = this.$refs.forMyFather.msg
this.fromMyChildrenOne = this.$refs.forMyFather.SendMyFather()
})
}
Grandson2代码:
data () {
return {
msg: '我是孙子组件2'
// msg2: ''
}
}
// ...........................................
methods: {
SendMyFather () {
var msg1 = '我很快乐'
return msg1
}
}
5:$parent 和 $children
GrandSon1代码:
<button @click='handerClick'>点击我更改父组件的值</button>
// .............................................
data () {
return {
msg: '我要提供一个值给父组件修改'
}
},
methods: {
handerClick () {
console.log(this.$parent)
this.$parent.msg3 = '我修改了父组件的值'
}
}
Children1代码:
<button @click="handleClickTwo">点击我用$children修改子组件的值</button>
// ..........................................................
data () {
return {
msg3: '我是即将被子组件修改的值'
}
}
// ...................................................
handleClickTwo () {
console.log(this.$children)
this.$children[0].msg = '我修改了子元素的值'
}
6:跨层级通信provide/inject
data () {
return {
msg: {
msg1: 'Hello My Grangson'
}
}
// ..................................
provide () {
// 里面可以接收对象或者函数
// provide: {
// msg: '我是。。。'
// } // 不是响应式的
// 普通传值:不是响应式的
return {
// 这么给值设置成响应式的呢?
// 给传递一个可遍历的对象,对象在data中声明,那么值就是可响应的,也就是修改后会影响子组件
msg1: this.msg
}
}
GrandSon2代码:
inject: ['msg1']
使用:
<h4>来自GrandFather的问候--------{{msg1.msg1}}</h4>
7:$attrs 和 $listeners
先一次性给子组件传值(或者函数),然后可以在一次全部的往下传,不用一个个传
APP.vue代码:
<ChildrenThree :messageOne="messageOne" :messageTwo="messageTwo" @test1='test1' @test2='test2'></ChildrenThree>
Children3代码:直接用$attrs就可以接收:
<h4>展示通过attrs传递过来的值{{$attrs.messageOne}}</h4>
<h4>展示通过attrs传递过来的值{{$attrs.messageTwo}}</h4>
// ......................................
test1 (value) {
// var msg5 = '我是test1事件传过去的'
this.msg6 = value
// this.test1 = msg5
// return msg5
},
test2 () {
var msg = '我是test2事件传递过来的'
return msg
}
Children3可以再全部往下传给GrandsSon3:
<!-- 通过v-bind可以继续往下传 -->
<GrandSonThree v-bind="$attrs" v-on='$listeners'></GrandSonThree>
grandSon3代码:
<h5>这是App.vue通过Children3给我传递过来的值-----{{$attrs.messageOne}}</h5>
<h5>这是App.vue通过Children3给我传递过来的值-----{{$attrs.messageTwo}}</h5>
<button @click='handlerClick'>利用$listeners操纵父级的父级的数据</button>
// ................................
methods: {
handlerClick () {
this.$listeners.test1('------------------')
}
}
8 localStorage/sessionStorage
localStorage:本地存储
seesionStorage:会话存储
9 Vuex 状态数据管理
10.v-model***
v-model…
页面展示: