学习vue的组件,可能很多人已经了解了组件的创建注册使用,但是随之而来的就是组件之间的通信,父子组件怎么传? 兄弟组件怎么传? 不是父子组件又怎么传?
接下来介绍几种组件之间的传参方式,也是很容易面试被问到的.
1.父传子用props
父组件传递参数给子组件的时候,可以使用props这个属性
<div id="app">
<cpn :cmsg="msg"></cpn>
</div>
<template id="cpn">
<div>
{{cmsg}}
</div>
</template>
<script src="../vue.js"></script>
<script>
var cpn = {
template:'#cpn',
// props:['cmsg'] props的格式有数组形式和对象形式
props:{
cmsg:{
type:String,
default:'1000'
}
},
// 如果是类型是Array/Object deafult必须是一个函数dafault(){} 例如 ↓
// props:{
// list:{
// type:Array,
// default() {
// return []
// }
// }
// }
}
var app = new Vue({
el:'#app',
data: {
msg:'我是父组件的消息'
},
components:{
cpn
}
})
</script>
运行结果
2.子传父用$emit
emit是发射的意思,也就是,子组件需要向父组件传递数据使用emit来发射一个自定义事件,在子组件上绑定该自定义事件,同时在父组件上有个对应的事件进行双向绑定事件,直接上代码.
<div id="app">
{{aaa}}
<cpn @itemfun='parentEvent'></cpn>
</div>
<template id="cpn">
<div>
<!-- 这里就需要绑定一个事件 -->
<button @click="btnClick">点击按钮发送自己的消息给俺爸爸</button>
</div>
</template>
<script src="../vue.js"></script>
<script>
var cpn = {
template:'#cpn',
data() {
return{
aa:'我是子组件上的信息'
}
},
methods: {
btnClick(){
this.$emit('itemfun',this.aa)
}
},
}
var app = new Vue({//根组件,也相当于是父组件
el:'#app',
data: {
aaa:'我将要被替换'
},
methods: {
parentEvent(val) {
console.log(val);
this.aaa = val
}
},
components:{
cpn
}
})
</script>
运行结果:
3.子访问父相互传使用 $refs
这是一重灰常人性化的 传参方式,其实也就是拿参数的一种简便方式 ,ref属性被用来给元素或者组件注册引用信息,引用信息会注册在父组件的$ref对象上(如果ref放在对象上,拿到的是原生节点,ref放在组件上,拿到的就是组件实例),我们先来看一下代码
我已经注册了两个组件,并且在vue根组件上使用,绑定了ref
我们可以去vue实例里面的生命周期函数mounted里面打印一下这个 this.$fefs ,看看能打印出什么信息.
mounted() {
console.log(this.$refs)
},
可以看大在控制台打印出了两个子组件实例,而且是一数组的方式存储,相当于ref='键名’
取出来的话使用this.$refs.aaa 这样就可以拿到这个组件实例
通过对象引用的方式就可以拿到不同组件实例上的不同参数和方法
这里子不能访问父.↓
4.父子相互访问 $parent / $root / $children
顾明思议,this.$parent 拿到的就是当前实例组件的父组件,记住是父组件,不是父组件之上的组件,他爸爸的爸爸已经是爷爷了,不是父亲了.而 this. $root 拿到的是根组件,也就是var app = new Vue({})
这个根组件实例.
查看$parent的内容
一起打印看看
5. 非父子组件(兄弟)组件之间的通信,EventBus,事件总线.
在vue中 是通过单独的事件中心来管理非父子组件,也就是兄弟组件之间的通信
1.建立事件中心
var EventBus = new Vue()
2.使用事件中心发射自定义事件
eventBus.$emit('自定义事件名',传递的数据)
3.使用事件中心接受数据
eventBus.$on('自定义事件名',[,callback])
下面看示例图
5. provide 和 inject 跨级传参
这两个参数是一起起作用的,允许一个祖先组件向起所有子孙后代注入一个依赖,不管组件层次有多深,都能建立起关系
provide:是一个对象,返回对象的一个函数,里面包含要给子孙属性的东西,也就是属性和属性值
inject: 一个字符串数组,或者是一个对象,属性值可以是一个对象,包含from和default默认值
from表示在可用的注入内容中收缩用的key,default当然也是默认值
6. 作用域插槽
我們先來想一个需求,假如子组件中有一组数据,但是想以不同的形式展示在父组件中,处理使用$emit等传参方式,也可以使用作用域插槽.
代码附上:
<div id="app">
<!-- 假如第一个组件里我们想以列表的形式展示 -->
<cpn v-slot='aa'>
<slot><ul v-for='item in aa.data'><li>{{item}}</li></ul></slot>
</cpn>
<!-- 假如第二个组件里我们想以' - ' 的方式来连接book数组里面的内容 -->
<cpn v-slot='bb'>
<span>{{bb.data.join('-')}}</span>
</cpn>
</div>
<template id="cpn">
<div>
<span>
<!-- 这里相当于给book起个别名叫做data -->
<slot :data='book'></slot>
</span>
</div>
</template>
<script src="../vue.js"></script>
<script>
var cpn = {
template:'#cpn',
data() {
return {
book:['飞鸽传书','天山雪莲','鲨鱼','翻身']
}
}
}
var app = new Vue({
el:'#app',
data: {
},
components:{
cpn
}
})
</script>
7.非父子组件又不同层次之间的 组件间的传值.
provide/inject:简单的来说就是在父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量。
需要注意的是这里不论子组件有多深,只要调用了inject那么就可以注入provider中的数据。而不是局限于只能从当前父组件的prop属性来获取数据
//父组件
<template>
<div>
<childOne></childOne>
</div>
</template>
<script>
import childOne from '../components/test/ChildOne'
export default {
name: "Parent",
provide: {
for: "demo"
},
components:{
childOne
}
}
子组件一
<template>
<div>
{{demo}}
<childtwo></childtwo>
</div>
</template>
<script>
import childtwo from './ChildTwo'
export default {
name: "childOne",
inject: ['for'],
data() {
return {
demo: this.for
}
},
components: {
childtwo
}
}
</script>
子组件二
<template>
<div>
{{demo}}
</div>
</template>
<script>
export default {
name: "",
inject: ['for'],
data() {
return {
demo: this.for
}
}
}
</script>
运行结果:
最后一个传参的代码是搬运的,也是很清晰明了.
这是一篇拖更了好久的文章,两三个星期前就差点写好了,忙活忙活就忘记补全发出去了,害…
各自努力,顶峰相见.加油