# slot插槽
插槽的使用过程其实是抽取共性、预留不同
<div id="app">
<zu-jian>
<div slot="s">shanghai</div>
<div slot="n">nanjing</div>
<div>333</div>
</zu-jian>
</div>
<script>
Vue.component("zuJian",{
template:`<div>
<slot></slot>
12
<slot name="n"></slot>
13
<slot name="ff">123</slot>
</div>`
})
var vm=new Vue({
el:"#app",
})
</script>
333
12
nanjing
13 123
父组件传输数值,其中有标签,会被转义到页面上,不符合我们的想法;若加层div包裹换成v-html形式又有代码冗余;
具名插槽; 若没有传入相对应插槽,可使用默认值;
无名插槽,只监控无名slot; 插槽具名在子组件view层内加slot=“xxx” 插槽在组件中的slot加上name=“xxx”即可对应
<div id="app">
<zujian slot-scope="items">
<h2>{{items.item}}</h2>
</zujian>
</div>
<script>
Vue.component("zujian",{
data:function(){
return{
list:[1,2,3,4,5,6]
}
},
template:`<div>
<slot v-for="item in list" :item="item"></slot>
</div>`
})
var vm =new Vue({
el:"#app",
})
</script>
作用域插槽
父组件在调用的子组件上加上slot-scope=“xxx”,接受子组件传过来的值,可以使用解构赋值的方法来处理,vue3已经废弃掉slot-scope
- xxx可随意定义;然后选中子组件模板传过来的值,这样的话,子组件渲染的内容标签也可以根据父组件的输入来自动适应,以上会返回h2标签
# vue2.6.x插槽语法变更
- 使用具名插槽时不要把v-slot加载在dom元素上,创建一个template放在上面。
根组件
<template>
<div>
<mo>
<!--slotProps可以为任何名,是从子组件传过来的内容,不过要和下面取值一致,作用读取子组件的值放在插槽里-->
<template v-slot:header="slotProps">
<h1>{{slotProps.header + ' ' + msg}}</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</mo>
</div>
</template>
<script>
import mo from './module.vue'
export default {
components: {
mo
},
data() {
return {
msg: '这是根组件的消息'
}
}
}
</script>
// 子组件
<template>
<div>
<!-- --header start-- -->
<header>
<slot name="header" :header="header"></slot>
</header>
<!-- --header over-- -->
<div>111</div>
<!-- --default start-- -->
<slot></slot>
<!-- --default over-- -->
<div>333</div>
<!-- --footer start-- -->
<footer>
<slot name="footer"></slot>
</footer>
<!-- --dooter over-- -->
</div>
</template>
<script>
export default {
data() {
return {
header: '来自子组件的头部消息'
}
}
}
</script>
<style scoped>
</style>
# 具名插槽简写
v-slot:header => #header
来自子组件的头部消息 这是根组件的消息
111
A paragraph for the main content.
And another one.
333
- 应用场景:子组件可能某些字段和功能不好复用在多个其他组件中,可以抽离出来以插槽的方式来实现
在vue的生命周期中可以通过this.$slot获取插槽的相关信息
# 作用域插槽
有时候希望插槽可以访问到子组件中的内容是非常重要的:
- 应用场景: 当一个组件被用来渲染一个数组元素时,使用插槽,并且希望插槽自定义显示每项的内容;
# 插槽实例
- 父组件:
v-slot 一般只能添加在 <template>,或者组件上,独占默认插槽的缩写可以不需要template而直接写在子组件上
<template>
<div>
<children1>
{{changeChildren1}}
</children1>
<hr/>
<children2 #f1>传了值的children2</children2>
<children2></children2>
<hr/>
<!-- v-slot can only be used on components or <template> tags. -->
<children3>
<template #footer>
footer
</template>
<template v-slot:header>
header {{changeChildren1}}
</template>
<template v-slot:default>
default
</template>
</children3>
<hr/>
<children4>
<template v-slot:other="otherSlotProps">
{{otherSlotProps.item}}
</template>
<template #title>
title
</template>
</children4>
<hr/>
<children5 :list="list">
<template v-slot:default="{Name, Age}"> <!-- 这里对对象slotProps作了解构 -->
{{Name}}: {{Age}}
</template>
</children5>
<hr/>
<button @click="change">button</button>
<children6>
<template v-slot:[changeSlot]>xxxx</template>
</children6>
</div>
</template>
<script setup lang="ts">
import children1 from './children1.vue';
import children2 from './children2.vue';
import children3 from './children3.vue';
import children4 from './children4.vue';
import children5 from './children5.vue';
import children6 from './children6.vue';
import {ref,Ref, reactive,toRefs} from 'vue'
let changeChildren1:Ref<string|number> = ref(0)
let data = reactive({
list:[
{ name: 'Tom', age: 23 },
{ name: 'Jack', age: 24 },
{ name: 'Steve', age: 25 },
]
})
let changeSlot = ref('')
let change = ()=>{
if((changeChildren1.value as number) % 2 === 0){
changeSlot.value ='k1'
}else{
changeSlot.value ='k2'
}
}
const {list} =toRefs(data)
setInterval(()=>{
if(typeof changeChildren1.value === 'number'){
changeChildren1.value++
}
},1000)
</script>
- children1:匿名插槽
<template>
<div>
子组件1匿名默认插槽:
<slot></slot>
</div>
</template>
- children2:插槽备用值
<template>
<div>
子组件2如果父组件没有传插槽内容:
<slot name="f1">没值使用这个</slot>
</div>
</template>
- children3:具名插槽
<template>
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
- children4: 作用域插槽=>子反馈父信息更新
<template>
<div>
作用域插槽:
<slot :item="item" name="other"></slot>
<br/>
<slot name="title"></slot>
</div>
</template>
<script setup lang="ts">
import {ref} from 'vue'
let item =ref(10)
</script>
- children5: 解构插槽
<template>
<div>
解构插槽 Prop:
<div class="Child">
<span v-for="item in list">
<slot :Name="item.name" :Age="item.age">{{item.name}} </slot>
<br/>
</span>
</div>
</div>
</template>
<script setup lang="ts">
import { defineProps, toRefs, toRef } from 'vue';
import type{PropType} from 'vue'
const props = defineProps({
list: {
type: Array as PropType<any[]>,
default() {
return [];
}
}
});
const { list } = toRefs(props);
</script>
- children6:动态插槽=>根据项目需求展示不同的插槽
<template>
<div>
动态插槽:
<div>
格子间1:
<slot name="k1">k1</slot>
</div>
<div>
格子间2:
<slot name="k2">k2</slot>
</div>
</div>
</template>