1 插槽slot
componentA:
<template>
<h3>ComponentA</h3>
<ComponentB>
<div>
<P>父组件传递的组件</P>
<p>{{ message }}</p>
</div>
</ComponentB>
</template>
<script>
import ComponentB from "./ComponentB.vue"
export default {
data(){
return{
message: "父组件传递的数据"
}
},
components:{
ComponentB
}
}
</script>
componentB:
<template>
<h3>ComponentB</h3>
<slot>默认值</slot>
</template>
<script>
export default {
data(){
return{
}
}
}
</script>
2 具名插槽
componentA:
<template>
<h3>ComponentA</h3>
<ComponentB>
<template v-slot:slot1>
<div>
<P>父组件传递的组件1</P>
<p>{{ message }}</p>
</div>
</template>
<template v-slot:slot2>
<div>
<p>父组件传递的组件2</p>
</div>
</template>
</ComponentB>
</template>
<script>
import ComponentB from "./ComponentB.vue"
export default {
data(){
return{
message: "父组件传递的数据"
}
},
components:{
ComponentB
}
}
</script>
componentB:
<template>
<h3>ComponentB</h3>
<slot name="slot1">默认值</slot>
<slot name="slot2">默认值</slot>
</template>
<script>
export default {
data(){
return{
}
}
}
</script>
如果componentB需要多次插入slot,但是不想重复某些内容,则需要使用<template v-slot:slot1><template>和<slot name="slot1"><slot>两个属性来指定。
3 插槽数据传递
componentA:
<template>
<h3>ComponentA</h3>
<ComponentB v-slot="sonData">
<p>{{ message }}---{{ sonData.msg }}</p>
</ComponentB>
</template>
<script>
import ComponentB from "./ComponentB.vue"
export default {
data(){
return{
message: "父组件传递的数据"
}
},
components:{
ComponentB
}
}
</script>
componentB:
<template>
<h3>ComponentB</h3>
<slot :msg="message"></slot>
</template>
<script>
export default {
data(){
return{
message: "子组件传递的数据"
}
}
}
</script>
如果父类和子类都要传递数据给插槽,父类直接传递即可,子类需要先传递给父类,父类使用v-slot接收,再将其传递给子类插槽。
4 具名插槽数据传递
componentA:
<template>
<h3>ComponentA</h3>
<ComponentB>
<template #header="sonData">
<p>{{ message }}---{{ sonData.msg }}</p>
</template>
</ComponentB>
</template>
<script>
import ComponentB from "./ComponentB.vue"
export default {
data(){
return{
message: "父组件传递的数据"
}
},
components:{
ComponentB
}
}
</script>
componentB:
<template>
<h3>ComponentB</h3>
<slot name="header" :msg="message"></slot>
</template>
<script>
export default {
data(){
return{
message: "子组件传递的数据"
}
}
}
</script>
5 组件切换&保持存活
App:
<template>
<keep-alive>
<component :is="tabComponent"></component>
</keep-alive>
<button @click="changeComponent">切换组件</button>
</template>
<script>
import {defineComponent} from "vue";
import ComponentA from "./components/ComponentA.vue"
import ComponentC from "./components/ComponentC.vue"
import ComponentD from "./components/ComponentD.vue"
export default defineComponent({
data(){
return{
tabComponent: "ComponentC"
}
},
components:{
ComponentA,
ComponentC,
ComponentD
},
methods:{
changeComponent(){
this.tabComponent = this.tabComponent === "ComponentC" ? "ComponentD" : "ComponentC"
}
}
})
</script>
ComponentC:
<template>
<h3>ComponentC</h3>
<p>{{ message }}</p>
<button @click="changeData">改变数据</button>
</template>
<script>
export default {
data(){
return{
message: "old"
}
},
methods:{
changeData(){
this.message = "new"
}
}
}
</script>
ComponentD:
<template>
<h3>ComponentD</h3>
</template>
<script setup>
</script>
6 异步加载组件
只需要修改App:
<template>
<keep-alive>
<component :is="tabComponent"></component>
</keep-alive>
<button @click="changeComponent">切换组件</button>
</template>
<script>
import {defineAsyncComponent, defineComponent} from "vue";
import ComponentA from "./components/ComponentA.vue"
import ComponentC from "./components/ComponentC.vue"
// 异步加载组件
const ComponentD = defineAsyncComponent(() =>
import("./components/ComponentD.vue")
)
export default defineComponent({
data(){
return{
tabComponent: "ComponentC"
}
},
components:{
ComponentA,
ComponentC,
ComponentD
},
methods:{
changeComponent(){
this.tabComponent = this.tabComponent === "ComponentC" ? "ComponentD" : "ComponentC"
}
}
})
</script>
7 注入依赖
在有多级继承组件时,最底层组件想要访问最顶层组件的数据,如果通过props实现,需要一层一层传递,会很麻烦。所以,这种情况可以使用provide和inject配合实现。