# 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

Here's some contact info

  • 应用场景:子组件可能某些字段和功能不好复用在多个其他组件中,可以抽离出来以插槽的方式来实现

在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>

vue3和vue2插槽 (opens new window)

最后更新: 7/27/2023, 7:47:30 PM