Vue面试之组件通信的方式总结
- props父子组件传参
- props父组件向子组件传参
- 数组形式
- 对象的简单形式
- 对象的复杂形式
- props子组件向父组件传参
- 通过传递方法的形式
- 通过传递事件的形式
- 插槽
- 默认插槽
- 具名插槽
- 作用域插槽
最近在整理一些前端面试中经常被问到的问题,分为vue相关、react相关、js相关、react相关等等专题,可持续关注后续内容,会不断进行整理~
在Vue框架中,提供了多种组件通信方式:props父子组件传参、插槽传参、Event Bus方式、vuex方式传参等,本篇先对前两种方法进行总结~
props父子组件传参
props父组件向子组件传参
props算是vue中比较简单的语法,通过在标签中定义属性的方式实现父组件对子组件的信息传递,关于传参的限定有三种方式:
需要注意的是,props是单向数据流传递,因此对接收到的props只是使用,不能修改!
数组形式
该方式是最为简单的方式,只需在接收prop的组件中以数组的形式备案要使用的props参数名即可,如下示例:
export default {name: 'xxx',props: ['name', 'age', 'sex']
}
对象的简单形式
如果想要指定接收props参数的类型,可通过此种方式进行简单限定,如:
export default {name: 'xxx',props: {name: String,age: Number,sex: String}
}
对象的复杂形式
如果还要对参数进行进一步的限制,如是否必输、默认值等,可采用此种方式进行限定:
export default {name: 'xxx',props: {name: {type: String,required: false,default: '小红'},age: {type: Number,required: true,default: 12},sex: {type: String,required: false}}
}
如果传递prop时没有满足对应限制,则会在控制台上报错。
props子组件向父组件传参
props也可实现子组件向父组件传递数据,即利用父组件向子组件传递事件/方法的形式,通过这种方式,在子组件使用父组件传过来的方法时,就可利用参数传递的方式,将参数传递给父组件,真是妙~
通过传递方法的形式
/* parent组件 * /
<Son :something="doSomething"></Son> // 将doSomething方法进行传递
export default {name: "Parent",components: {Son,},methods: {doSomething(name) {console.log(name, '这就是由子组件传递过来的name值');},},
};
// Son组件
<template><button @click="do">点击触发方法</button>
</template>
<script>
import Son from './Son.vue';
export default {name: 'Son',props: ['something']
}
do() {this.something('小明') // 将子组件的参数传递给父组件
}
</script>
通过传递事件的形式
上述方法也可以通过$emit方法来调用父组件方法,从而将子组件参数传递给父组件,修改如下:
// 父组件
<template><Son @doSomething="something"></Son>
</template>
<script>
import Son from './Son.vue';export default {name: 'Parent',components: {Son}methods: {something(params) {console.log('拿到子组件传递过来的参数', params)}}}
</script>
// 子组件
<template><Button @click="do"></Button>
</template>
<script>export default {name: 'Son',methods: {do() {this.$emit('doSomething', '小红') // 触发父组件的doSomething事件,并将'小红'传递出去}}}
</script>
插槽
Vue提供了插槽机制,所谓插槽是指我现在这块地方要写一些内容,但是内容还不确定,因此我在此处用插槽占上位置,等后续在别处补充好了内容,就可以在此处展现出来效果。插槽用slot标签表示,有默认插槽、具名插槽以及作用域插槽三种;而插槽的内容要写在组件标签之间,如
<A>此处即为插槽内容</A>
插槽的官方说法如下:
插槽作为组件的内容分发出口。它允许在父组件中,将任意子组件的内容“插入”到组件模板中的特定位置,以便在不同的场景下展示不同的内容。插槽提供了一种灵活的方式来组合父组件和子组件的内容,并允许创建更灵活、可复用的组件。
默认插槽
默认插槽是最简单的一种,形如:
<slot><slot>
<template><div>这是Parent组件</div><Son>插槽内容</Son>
</template>
<script>
import Son from './Son.vue';export default {name: 'Parent',components: {'B'}...}
</script>
<template><div>这是Son组件</div><slot></slot> // 插槽中的内容就会替换到这里
</template>
<script>export default {name: 'Son',...}
</script>
具名插槽
见名之意,就是为不同插槽起不同的名字,用于区分不同插槽;通过在slot标签中设置name属性即可;
<template><header><slot name="header"></slot></header><main><slot name="main"></slot></main><footer><slot name="footer"></slot></footer>
</template>
在向具名插槽提供内容时,可通过template标签设置slot指令指定其名称,如:
<template><div>这是Parent组件</div><Son><template slot="header">这是标题内容.....</template><template slot="main">这是主要内容.....</template><template slot="footer">这是底部内容.....</template></Son>
</template>
<script>export default {name: 'Parent',components: {'B'}...}
</script>
作用域插槽
如果想要将父组件访问子组件数据,此时可以使用作用域插槽方法,简单来说,就是在子组件slot标签上定义要传递的参数prop,这样在父组件中就可以通过slot-scope属性定义;
作用域插槽(或称为具名插槽的插槽内容作用域)允许子组件将数据传递给父组件,并且在父组件中可以直接访问和使用这些数据。
// Son组件
<template><div><div>son组件</div><slot :obj="obj"></slot> // 利用prop将obj数据传出去</div>
</template>
// Parent组件
<template><div><div>parent组件</div><template slot-scope="data">{{data.obj}} // 这里就可以拿到传递过来的数据obj,data可以随便定义</template></div>
</template>
以上示例皆是基于Vue2版本,在Vue3中,使用v-slot代替了slot-scope,在使用具名插槽和作用域插槽时要注意区分~