前端Vue日常工作中--关于插槽slot

180 阅读4分钟

前端Vue日常工作中--关于插槽slot

1.插槽种类简单说明

在 Vue.js 中,插槽(Slot)是一种强大的机制,允许父组件向子组件传递内容,并在子组件中进行自定义渲染。插槽是一种实现组件复用和灵活性的关键特性。

1. 基本插槽

  • 父组件中的使用:

    <template>
      <div>
        <child-component>
          <!-- 父组件中通过 <slot> 标签定义插槽 -->
          <p>This is content from the parent component.</p>
        </child-component>
      </div>
    </template>
    
  • 子组件中的使用:

    <template>
      <div>
        <!-- 子组件中通过 <slot> 标签插入父组件传递的内容 -->
        <slot></slot>
      </div>
    </template>
    

父组件通过 <slot> 标签定义了一个插槽,子组件中使用 <slot> 标签插入了父组件传递的内容。

2. 具名插槽

具名插槽允许父组件传递多个插槽内容到子组件中。

  • 父组件中的使用:

    <template>
      <div>
        <child-component>
          <!-- 使用具名插槽 -->
          <template v-slot:header>
            <h2>This is the header</h2>
          </template>
          <template v-slot:footer>
            <p>This is the footer</p>
          </template>
        </child-component>
      </div>
    </template>
    
  • 子组件中的使用:

    <template>
      <div>
        <header>
          <!-- 使用具名插槽 -->
          <slot name="header"></slot>
        </header>
        <main>
          <!-- 默认插槽 -->
          <slot></slot>
        </main>
        <footer>
          <!-- 使用具名插槽 -->
          <slot name="footer"></slot>
        </footer>
      </div>
    </template>
    

父组件通过 v-slot# 符号为插槽取了名字,而子组件中使用 <slot> 标签时,通过 name 属性指定了要插入的具名插槽。

3. 作用域插槽

作用域插槽允许父组件传递数据到子组件,并在子组件中使用该数据。

  • 父组件中的使用:

    <template>
      <div>
        <child-component>
          <!-- 使用作用域插槽 -->
          <template v-slot:default="slotProps">
            <p>{{ slotProps.message }}</p>
          </template>
        </child-component>
      </div>
    </template>
    
  • 子组件中的使用:

    <template>
      <div>
        <!-- 使用作用域插槽 -->
        <slot :message="dataFromParent"></slot>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          dataFromParent: 'Hello from parent!',
        };
      },
    };
    </script>
    

通过 v-slot 定义了一个作用域插槽,子组件使用 slot 标签时,通过 :message 绑定了一个属性,这样就能够在子组件中获取到父组件传递的数据。

2.<template #>

在Vue.js中,<template> 元素内部的 # 符号用于定义插槽(slot)。这种插槽定义方式被称为“具名插槽”(Named Slots)或“作用域插槽”(Scoped Slots)。

当使用Element UI(基于Vue.js)时,<template #> 通常用于定义和使用插槽,以实现更灵活的组件化开发。

  1. 具名插槽(Named Slots)

    具名插槽允许在组件中的特定位置插入内容。在Element UI中,有些组件提供了具名插槽,例如 <el-table><el-dialog>

    <el-table>
      <el-table-column label="Name">
        <!-- 使用具名插槽 #header 定义表头 -->
        <template #header>
          <span>Custom Header</span>
        </template>
        <!-- 使用默认插槽定义表格内容 -->
        {{rowData.name}}
      </el-table-column>
    </el-table>
    
  2. 作用域插槽(Scoped Slots)

    作用域插槽允许父组件向子组件传递数据,并在子组件中使用该数据。在Element UI中,有些组件支持作用域插槽,例如 <el-select><el-table-column>

    <el-select v-model="selectedItem">
      <!-- 使用作用域插槽 #default 接收数据并显示 -->
      <template #default="{ item }">
        <span>{{ item.label }}</span>
      </template>
      <el-option v-for="option in options" :key="option.value" :label="option.label" :value="option.value"></el-option>
    </el-select>
    

    <el-select> 的每个选项都通过作用域插槽 #default 接收了数据,并在模板中显示。

  3. 插槽属性

    Element UI的一些组件还支持插槽属性,通过插槽属性,可以进一步控制插槽的行为。例如,<el-dialog> 提供了 slot-scope 属性,用于定义插槽作用域:

    <el-dialog :visible.sync="dialogVisible">
      <!-- 使用 slot-scope 定义插槽作用域 -->
      <template #title="{ close }">
        <span>Custom Title</span>
        <!-- 在作用域中使用 close 方法关闭对话框 -->
        <i @click="close">X</i>
      </template>
      <p>Dialog Content</p>
    </el-dialog>
    

    #title 插槽通过 slot-scope 接收了 close 方法,可以在作用域中使用该方法关闭对话框。

3.插槽属性(slot-scope)

在 Vue.js 中,插槽属性是用于定制和控制插槽行为的一种机制。Vue.js 2.x 中,插槽属性通常通过 slot-scope 来实现,在 Vue.js 3.x 中,被替代为 v-slot。在 Element UI 中,一些组件提供了插槽属性,以便在使用插槽时更加灵活。

1. 使用方法

在子组件中,通过 slot-scope 将数据传递给插槽。具体做法是在插槽上使用 slot-scope 属性:

<template>
  <div>
    <!-- 使用 slot-scope 将数据传递给插槽 -->
    <slot :data="someData"></slot>
  </div>
</template>

<script>
export default {
  data() {
    return {
      someData: 'Hello from child!',
    };
  },
};
</script>

在父组件中,使用 v-slot# 符号来接收传递的数据:

<template>
  <div>
    <child-component>
      <!-- 使用作用域插槽接收数据 -->
      <template v-slot:default="scope">
        <p>{{ scope.data }}</p>
      </template>
    </child-component>
  </div>
</template>

或者使用缩写形式 #

<!-- 父组件 -->
<template>
  <div>
    <child-component>
      <!-- 使用作用域插槽接收数据的缩写形式 -->
      <template #default="scope">
        <p>{{ scope.data }}</p>
      </template>
    </child-component>
  </div>
</template>

2. 使用多个作用域插槽

如果在子组件中有多个插槽需要传递数据,可以为每个插槽定义不同的作用域:

<template>
  <div>
    <!-- 使用多个作用域插槽 -->
    <slot :headerData="headerData" :contentData="contentData"></slot>
  </div>
</template>

<script>
export default {
  data() {
    return {
      headerData: 'Header from child!',
      contentData: 'Content from child!',
    };
  },
};
</script>

在父组件中分别接收这些数据:

<template>
  <div>
    <child-component>
      <!-- 使用多个作用域插槽接收数据 -->
      <template v-slot:header="scope">
        <h2>{{ scope.headerData }}</h2>
      </template>
      <template v-slot:content="scope">
        <p>{{ scope.contentData }}</p>
      </template>
    </child-component>
  </div>
</template>

3.说明

  1. slot-scope

    • 用法: <template slot-scope="props"> 或者 <template #default="props">

    • 详细说明: slot-scope 用于定义作用域插槽,允许父组件向子组件传递数据。在插槽内部,通过 props 对象可以访问传递过来的数据。

    • 例子:

      <!-- 父组件 -->
      <template>
        <child-component>
          <template #default="props">
            <span>{{ props.item }}</span>
          </template>
        </child-component>
      </template>
      
      <!-- 子组件 -->
      <script>
      export default {
        data() {
          return {
            items: [1, 2, 3],
          };
        },
      };
      </script>
      
      <template>
        <ul>
          <li v-for="item in items">
            <!-- 使用 slot-scope 定义作用域插槽 -->
            <slot :item="item"></slot>
          </li>
        </ul>
      </template>
      
  2. slot-scope 对象

    • 用法: <template slot-scope="{ prop1, prop2 }"> 或者 <template #default="{ prop1, prop2 }">

    • 详细说明: slot-scope 可以接受一个对象,该对象包含了通过插槽传递的多个属性。这使得可以更方便地在插槽内使用多个属性。

    • 例子:

      <!-- 父组件 -->
      <template>
        <child-component>
          <template #default="{ item, index }">
            <span>{{ index + 1 }}. {{ item }}</span>
          </template>
        </child-component>
      </template>
      
      <!-- 子组件 -->
      <script>
      export default {
        data() {
          return {
            items: ['A', 'B', 'C'],
          };
        },
      };
      </script>
      
      <template>
        <ul>
          <li v-for="(item, index) in items">
            <!-- 使用 slot-scope 对象定义作用域插槽 -->
            <slot :item="item" :index="index"></slot>
          </li>
        </ul>
      </template>
      
  3. 插槽属性的传递

    • 用法: <slot :prop="value"></slot>

    • 详细说明: 父组件通过在插槽上使用属性绑定的方式,将数据传递给子组件的插槽。

    • 例子:

      <!-- 父组件 -->
      <template>
        <child-component>
          <template #default="props">
            <span>{{ props.title }}</span>
          </template>
        </child-component>
      </template>
      
      <!-- 子组件 -->
      <script>
      export default {
        data() {
          return {
            title: 'Hello, World!',
          };
        },
      };
      </script>
      
      <template>
        <div>
          <!-- 通过插槽属性传递数据 -->
          <slot :title="title"></slot>
        </div>
      </template>
      

`