vue中slot的使用

183 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第15天,点击查看活动详情

一、简介

slot 是对子组件的扩展可以通过<slot>插槽向子组件内部指定位置传递内容

插槽出口<slot>

<slot> 元素是一个插槽出口,表示了父元素提供的插槽内容(slot content)在哪里被渲染 插槽内容可以是任意合法的模板内容,不局限于文本。 插槽的显示位置由子组件决定

slotprops 的区别

设计思想

props设计思想是传递状态,贯彻数据驱动组件的概念,子组件的渲染取决于父组件传递的数据 slot 设计思想是传递DOM节点,将父组件的模板代码节点直接传递给子组件的某个slot

作用范围

父组件在调用子组件的时候申请并赋值变量,子组件内将其加入props列表后,就可以接收并使用,但是一旦传递过来,作用域就发生变化, 子组件虽然为父组件预留slot,但是slot的作用域依然属于父组件,可以访问到父组件内的所有状态。 插槽内容无法访问子组件的数据,

二、slot 类型

匿名插槽(默认插槽)

没有设置name属性的插槽 在组件只有一个插槽时,可不设置slot name 属性,父组件使可v-slot 后可以不带参数, 注意: 插槽可以放置在组件的任意位置, 一个组件只有一个匿名插槽 匿名插槽只能作为没有slot属性的元素的插槽

//chile.vue
<div class="child">
    <h1>子组件</h1>
     <slot name="head">头部默认值</slot>
     <slot>这是个匿名插槽(没有name属性)</slot>
     <slot name="body">主体默认值</slot>
 </div>
//parent.vue
<div class="parent">
 <h1>父组件</h1>
 <child>
     <p slot="head">我是头部</p>
     <p>我是其他内容</p>
 </child>
 </div>

结果

我是头部 (具名插槽name 默认值被覆盖)

我是其他内容 (匿名插槽 默认值被覆盖)

主体默认值(具名插槽body 默认值被渲染)

具名插槽

带 name 的插槽被称为具名插槽 (named slots)。没有提供 name 的 <slot> 出口会隐式地命名为“default”。

v-slot 有对应的简写 #,因此 <template v-slot:header> 可以简写为 <template #header><template v-slot:插槽名称>插槽内容</template> 等于 <p slot="插槽名称">插槽内容</p>

一个组件可以由很多具名插槽,具名插槽可以出现在任意位置 注意:

  1. 带有 v-slot 的<template> 元素中的所有内容都将会被传入相应的插槽。
  2. 任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容。
  3. slot 可以用在任何元素上,v-slot 只能添加在 <template> 上
  4. 当一个组件同时接收默认插槽和具名插槽时,所有位于顶级的非 <template> 节点都被隐式地视为默认插槽的内容

作用域插槽

同时使用父组件域内和子组件域内的数据,让子组件在渲染时将一部分数据提供给插槽,可以相对组件传递props,向上一个插槽的出口传递attributes

//1、使用v-slot 接收
<MyComponent v-slot="slotProps">
    {{ slotProps.text }} {{ slotProps.count }}
</MyComponent>
​
//2、结构赋值
<MyComponent v-slot="{ text, count }">
  {{ text }} {{ count }}
</MyComponent>
​
//3具名插槽传值
<MyComponent>
    <template #header="headerProps"> 
       {{ headerProps }}   //headerProps 是{message:hello} key-value 形式
    </template> 
     <template v-slot:footer="footerProps"> 
       {{ footerProps }} 
    </template>
    <template #default="defaultProps">
        {{ defaultProps }}
    </template> 
</MyComponent>
// 插槽
<slot name="header" message="hello"></slot>