????在Vue框架中,提供了多种组件通信方式:props父子组件传参、插槽传参、Event Bus方式、vuex方式传参等,本篇先对前两种方法进行总结~
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也可实现子组件向父组件传递数据,即利用父组件向子组件传递事件/方法的形式,通过这种方式,在子组件使用父组件传过来的方法时,就可利用参数传递的方式,将参数传递给父组件,真是妙~
/* 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,在使用具名插槽和作用域插槽时要注意区分~