【转】vue的7种常见通信
一、props
/ $emit
Prop
是你可以在组件上注册的一些自定义特性。当一个值传递给一个 prop
特性的时候,它就变成了那个组件实例的一个属性。和react的props类似。
// Demo父组件
<template>
<div class="father">
/** 向子组件传值 */
<Child :age="age"></Child>
</div>
</template>
<script>
import Child from './child.vue'
export default {
name: 'child',
components: { Child },
data() {
return {
age: 12
}
}
}
</script>
// 子组件中使用props
<template>
<div>
{{age}}
</div>
</template>
<script>
export default {
props: {
age: {
type: Number
}
}
}
</script>
$emit
触发当前实例上的事件。附加参数都会传给监听器回调。
<template>
<div @click="callFatherListener">
{{age}}
</div>
</template>
<script>
export default {
props: {
age: {
type: Number
}
},
methods: {
callFatherListener () {
// 点击时,调用父组件的方法,前提是该方法已被注册
this.$emit('fatherEvent', 'msg from son')
}
}
}
</script>
// ---父组件中---
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<!-- 父组件注册这个事件监听器,当被子组件调用后会捕获-->
<Son :age="1" @fatherEvent="fatherEvent"></Son>
</div>
</template>
<script>
import Son from './Son'
export default {
components: {Son},
name: 'Father',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
methods: {
fatherEvent (msg) {
console.log(msg)
}
}
}
</script>
二、
$parent
/ $children
指定已创建的实例之父实例,在两者之间建立父子关系。子实例可以用this.$parent
访问父实例,子实例被推入父实例的 $children
数组中。
<!--父组件中-->
<template>
<div class="hello">
<h1 @click="changeSonMsg">点击改变子组件的值</h1>
<Son></Son>
</div>
</template>
<script>
import Son from './Son'
export default {
components: {Son},
name: 'Father',
data () {
return {
msg: '爸爸的msg'
}
},
methods: {
changeSonMsg () {
// 改变子组件的值
this.$children[0].msg = 'change from father'
// 调用父组件的方法
this.$children[0].sonFunc('儿子你给我嘿嘿嘿')
},
fatherFunc () {
console.log('爸爸你也嘿嘿嘿')
}
}
}
</script>
<!--子组件中-->
<template>
<div>
{{msg}}
<p @click="callFatherFunc">获取爸爸组件的值为: {{fatherVal}}</p>
</div>
</template>
<script>
export default {
data () {
return {
msg: 'default msg'
}
},
methods: {
sonFunc (msg) {
console.log(msg)
},
callFatherFunc () {
// 调用父组件的方法
this.$parent.fatherFunc()
}
},
computed: {
fatherVal () {
// 通过$parent获取父组件的属性
return this.$parent.msg
}
}
}
</script>
要注意边界情况,如在
#app
上拿$parent
得到的是new Vue()
的实例,在这实例上再拿$parent
得到的是undefined
,而在最底层的子组件拿$children
是个空数组。也要注意得到$parent
和$children
的值不一样,$children
的值是数组,而$parent
是个对象,另外根实例可以通过 $root
拿到。三、
provide
/ inject
- 2.2.0 新增
- 无论嵌套多深,都能通信
provide
选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的属性。inject
选项应该是:- 一个字符串数组,或
- 一个对象,对象的 key 是本地的绑定名
<!--父组件中--> <template> <div class="hello"> <Son></Son> </div> </template> <script> import Son from './Son' export default { components: {Son}, name: 'Father', provide: { for: 'Father provide msg' } } </script> <!--子组件中--> <template> <div> 父级获取的属性: {{msg}} </div> </template> <script> export default { data () { return { msg: this.for } }, inject: ['for'] } </script>
provide
和inject
主要为高阶插件/组件库提供用例,所以这里有个笔者写的一个高级的例子。四、ref
/ refs
ref
被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs
对象上。如果在普通的 DOM
元素上使用,引用指向的就是 DOM
元素;如果用在子组件上,引用就指向组件实例。
<!--子组件中-->
<template>
<div>
{{msg}}
</div>
</template>
<script>
export default {
data () {
return {
msg: 'son\'s msg'
}
}
}
</script>
<!--父组件中-->
<template>
<div class="hello">
<Son ref="son"></Son>
<p @click="showSonMsg">点击打印son的msg</p>
</div>
</template>
<script>
import Son from './Son'
export default {
components: {Son},
name: 'Father',
methods: {
showSonMsg () {
console.log(this.$refs.son.msg)
}
}
}
</script>
五、eventBus
eventBus
又称事件总线,笔者用的很少,具体可以去官网。vuex
加入后,对组件之间的通信有了更加清晰的操作,对于中大型的项目来说,一开始就把vuex
的使用计划在内是明智的选择。六 、vuex
组件不允许直接修改属于 store 实例的 state,而应执行 action 来分发 (dispatch) 事件通知 store 去改变,我们最终达成了 Flux 架构。这样约定的好处是,我们能够记录所有 store 中发生的 state 改变
this.$store.commit('selectMenu',"xxx")
总结
父子关系可以用props-$emit,parent-children等,如果是兄弟层级或关联度不高的组件之间的通信,推荐使用vuex。
借用官方的说法,一般简单项目没必要使用vuex,中大型项目复制项目建议使用vuex。
和redux相比,react16.8以后推出hook,借用阮一峰老师的话,'这个api是react的未来'。
七、localstorage和sessionStorage
应该说不单是vue,凡是前端都可以用这种方式通信,跨页面跨层级的。
阮一峰 react hook入门:http://www.ruanyifeng.com/blog/2019/09/react-hooks.html
阮一峰react技术栈系列:http://www.ruanyifeng.com/blog/2016/09/react-technology-stack.html
原文链接:https://www.jianshu.com/p/6c776936083c阮一峰react技术栈系列:http://www.ruanyifeng.com/blog/2016/09/react-technology-stack.html