vue-08(使用slot进行灵活的组件渲染)

news2025/6/2 14:25:04

使用slot进行灵活的组件渲染

作用域slot是 Vue.js 中的一种强大机制,它允许父组件自定义子组件内容的呈现。与仅向下传递数据的常规 props 不同,作用域 slot 为父级提供了一个模板,然后子级可以填充数据。这提供了高度的灵活性和可重用性,使您能够创建可适应各种上下文的组件,而无需修改其核心逻辑。本章将探索 scoped slot 的概念、它们的语法,以及如何使用它们来构建灵活且可重用的组件。

了解作用域插槽

作用域插槽 是一种特殊类型的插槽,它允许父组件访问子组件的数据。这是通过将数据作为 props 传递给插槽来实现的。然后,父组件使用此数据以自定义方式呈现插槽内容。

基本语法

使用作用域插槽的基本语法包括在子组件中定义一个插槽,然后在父组件中为该插槽提供模板。

子组件(例如 MyList.vue):

<template>
  <div>
    <ul>
      <li v-for="item in items" :key="item.id">
        <slot name="item" :item="item">{{ item.name }}</slot>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  props: {
    items: {
      type: Array,
      required: true,
    },
  },
};
</script>

在这个例子中,<slot> 元素有一个 name 属性设置为 “item” 和一个 :item 属性,该属性将当前itemv-for 循环绑定到插槽的范围。{{ item.name }} 是父组件未为槽提供自定义模板时将呈现的回退内容。

父组件:

<template>
  <div>
    <MyList :items="myItems">
      <template v-slot:item="slotProps">
        <strong>{{ slotProps.item.name }}</strong> - <em>{{ slotProps.item.description }}</em>
      </template>
    </MyList>
  </div>
</template>

<script>
import MyList from './MyList.vue';

export default {
  components: {
    MyList,
  },
  data() {
    return {
      myItems: [
        { id: 1, name: 'Apple', description: 'A crisp and juicy fruit' },
        { id: 2, name: 'Banana', description: 'A sweet and potassium-rich fruit' },
      ],
    };
  },
};
</script>

在这里, <template v-slot:item="slotProps"> 语法为 MyList 组件中的 “item” 插槽定义了一个作用域插槽。slotProps 变量是一个对象,其中包含从子组件(在本例中为 item 对象)传递的数据。然后,父组件使用此数据以自定义格式呈现插槽内容。

速记语法

Vue.js 使用 # 字符为作用域插槽提供简写语法。可以使用简写语法重写前面的示例,如下所示:

<template>
  <div>
    <MyList :items="myItems">
      <template #item="slotProps">
        <strong>{{ slotProps.item.name }}</strong> - <em>{{ slotProps.item.description }}</em>
      </template>
    </MyList>
  </div>
</template>

#item=“slotProps” 等同于 v-slot:item=“slotProps”。 这种速记语法更简洁,通常是首选。

带有 Scoped Props 的默认插槽

作用域插槽也可以与默认插槽(没有 name 属性的插槽)一起使用。在这种情况下,父组件为默认插槽提供模板,并且可以访问从子组件传递的数据。

子组件:

<template>
  <div>
    <slot :message="greeting"></slot>
  </div>
</template>

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

父组件:

<template>
  <div>
    <MyComponent>
      <template #default="slotProps">
        {{ slotProps.message }}
      </template>
    </MyComponent>
  </div>
</template>

<script>
import MyComponent from './MyComponent.vue';

export default {
  components: {
    MyComponent,
  },
};
</script>

在此示例中,子组件将 message 属性传递给 default 插槽。然后,父组件使用此 prop 来渲染插槽内容。

实际示例和演示

让我们探索一些实际的例子,说明如何使用作用域 slot 来构建灵活且可重用的组件。

示例 1:可自定义的表组件

作用域 slots 的一个常见用例是创建可自定义的 table 组件。table 组件可以提供表的基本结构,而父组件可以定义每个单元格的呈现方式。

表格组件 (MyTable.vue):

<template>
  <table>
    <thead>
      <tr>
        <th v-for="header in headers" :key="header.key">{{ header.label }}</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="row in items" :key="row.id">
        <td v-for="header in headers" :key="header.key">
          <slot :name="header.key" :row="row">{{ row[header.key] }}</slot>
        </td>
      </tr>
    </tbody>
  </table>
</template>

<script>
export default {
  props: {
    headers: {
      type: Array,
      required: true,
    },
    items: {
      type: Array,
      required: true,
    },
  },
};
</script>

父组件:

<template>
  <div>
    <MyTable :headers="tableHeaders" :items="tableData">
      <template #name="slotProps">
        <strong>{{ slotProps.row.name }}</strong>
      </template>
      <template #age="slotProps">
        <em>{{ slotProps.row.age }}</em>
      </template>
    </MyTable>
  </div>
</template>

<script>
import MyTable from './MyTable.vue';

export default {
  components: {
    MyTable,
  },
  data() {
    return {
      tableHeaders: [
        { key: 'name', label: 'Name' },
        { key: 'age', label: 'Age' },
        { key: 'city', label: 'City' },
      ],
      tableData: [
        { id: 1, name: 'John Doe', age: 30, city: 'New York' },
        { id: 2, name: 'Jane Smith', age: 25, city: 'Los Angeles' },
      ],
    };
  },
};
</script>

在此示例中,MyTable 组件基于 headersitems 属性呈现一个表。父组件使用作用域插槽来自定义 “name” 和 “age” 列的呈现。“city” 列将使用 MyTable 组件中定义的默认内容。

示例 2:可自定义的列表组件

另一个常见用例是创建可自定义的列表组件。列表组件可以提供列表的基本结构,而父组件可以定义每个项目的呈现方式。

列表组件 (MyList.vue):

<template>
  <ul>
    <li v-for="item in items" :key="item.id">
      <slot name="item" :item="item">{{ item.name }}</slot>
    </li>
  </ul>
</template>

<script>
export default {
  props: {
    items: {
      type: Array,
      required: true,
    },
  },
};
</script>

父组件:

<template>
  <div>
    <MyList :items="myItems">
      <template #item="slotProps">
        <a :href="slotProps.item.url">{{ slotProps.item.name }}</a>
      </template>
    </MyList>
  </div>
</template>

<script>
import MyList from './MyList.vue';

export default {
  components: {
    MyList,
  },
  data() {
    return {
      myItems: [
        { id: 1, name: 'Google', url: 'https://www.google.com' },
        { id: 2, name: 'Facebook', url: 'https://www.facebook.com' },
      ],
    };
  },
};
</script>

在此示例中,MyList 组件根据 items 属性呈现项目列表。父组件使用一个有范围的插槽来自定义每个项目的渲染,将其转换为链接。

示例 3:具有验证的表单输入组件

范围插槽可用于创建高度可定制的表单输入组件。该组件可以处理输入逻辑和验证,而父组件可以自定义输入的外观和错误消息。

输入组件 (MyInput.vue):

<template>
  <div>
    <label :for="id">{{ label }}</label>
    <input
      :id="id"
      :type="type"
      :value="value"
      @input="$emit('update:value', $event.target.value)"
    />
    <div v-if="error">
      <slot name="error" :error="error">{{ error }}</slot>
    </div>
  </div>
</template>

<script>
import { ref, watch } from 'vue';

export default {
  props: {
    id: {
      type: String,
      required: true,
    },
    label: {
      type: String,
      required: true,
    },
    type: {
      type: String,
      default: 'text',
    },
    value: {
      type: String,
      default: '',
    },
    rules: {
      type: Array,
      default: () => [],
    },
  },
  emits: ['update:value'],
  setup(props) {
    const error = ref('');

    watch(
      () => props.value,
      (newValue) => {
        for (const rule of props.rules) {
          const validationResult = rule(newValue);
          if (validationResult) {
            error.value = validationResult;
            return;
          }
        }
        error.value = '';
      }
    );

    return {
      error,
    };
  },
};
</script>

父组件:

<template>
  <div>
    <MyInput
      id="name"
      label="Name"
      type="text"
      :value="name"
      @update:value="name = $event"
      :rules="[requiredRule, minLengthRule]"
    >
      <template #error="slotProps">
        <span style="color: red;">{{ slotProps.error }}</span>
      </template>
    </MyInput>
  </div>
</template>

<script>
import MyInput from './MyInput.vue';

export default {
  components: {
    MyInput,
  },
  data() {
    return {
      name: '',
    };
  },
  setup() {
    const requiredRule = (value) => {
      if (!value) {
        return 'This field is required.';
      }
      return null;
    };

    const minLengthRule = (value) => {
      if (value.length < 3) {
        return 'This field must be at least 3 characters long.';
      }
      return null;
    };

    return {
      requiredRule,
      minLengthRule,
    };
  },
};
</script>

在此示例中,MyInput 组件处理输入逻辑和验证。父组件使用 scoped slot 来自定义错误消息的渲染。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2394429.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Fine Pruned Tiled Light Lists(精细删减的分块光照列表)

概括 在这篇文章&#xff0c; 我将介绍一种Tiled Light 变体&#xff0c;主要针对AMD Graphics Core Next&#xff08;GCN&#xff09;架构进行优化&#xff0c;我们的方法应用于游戏 古墓丽影:崛起 中&#xff0c;特别是我们在通过光列表生成和阴影贴图渲染之间交错进行异步计…

openresty+lua+redis把非正常访问的域名加入黑名单

一、验证lua geoIp2是否缺少依赖 1、执行命令 /usr/local/openresty/bin/opm get anjia0532/lua-resty-maxminddb 执行安装命令报错,缺少Digest/MD5依赖 2、Digest/MD5依赖 yum -y install perl-Digest-MD5 GeoIP2 lua库依赖动态库安装&#xff0c;lua库依赖libmaxminddb实…

使用Mathematica绘制随机多项式的根

使用ListPlot和NSolve直接绘制&#xff1a; (*返回系数为r和s之间整数的n次随机多项式*) eq[n_, r_, s_] : RandomInteger[{r, s}, {n}] . Array[Power[x, # - 1] &, n] (*返回给定随机多项式的根所对应的笛卡尔坐标*) sol[n_, r_, s_] : {Re[#], Im[#]} & / (x /.…

IEEE PRMVAI 2025 WS 26:计算机视觉前沿 Workshop 来袭!

宝子们&#xff0c;搞计算机视觉和深度学习的看过来啦&#xff01;&#x1f389; 2025 年 IEEE 第三届模式识别、机器视觉和人工智能国际会议里&#xff0c;Workshop 26 简直是科研宝藏地&#xff01; 这次 Workshop 聚焦 “Deep learning - based low - level models for comp…

360浏览器设置主题

设置默认主题&#xff1a; 1.右上角有个皮肤按钮 进来后&#xff0c;右边有个回复默认皮肤按钮。 换成彩色皮肤后&#xff0c;找按钮不太好找了。

最卸载器——Geek Uninstaller 使用指南

Geek Uninstaller 是一款轻量级的第三方卸载工具&#xff0c;专为 Windows 系统设计&#xff0c;提供比系统默认卸载器更彻底的应用清除能力。它体积小、绿色免安装&#xff0c;使用起来简单直观&#xff0c;但功能却不含糊。 一、为什么要用 Geek Uninstaller&#xff1f; Wi…

应急响应靶机-web3-知攻善防实验室

题目&#xff1a; 1.攻击者的两个IP地址 2.攻击者隐藏用户名称 3.三个攻击者留下的flag 密码&#xff1a;yj123456 解题&#xff1a; 1.攻击者的两个IP地址 一个可能是远程&#xff0c;D盾&#xff0c;404.php,192.168.75.129 找到远程连接相关的英文,1149代表远程连接成功…

【基于SpringBoot的图书购买系统】Redis中的数据以分页的形式展示:从配置到前后端交互的完整实现

引言 在当今互联网应用开发中&#xff0c;高性能和高并发已经成为系统设计的核心考量因素。Redis作为一款高性能的内存数据库&#xff0c;以其快速的读写速度、丰富的数据结构和灵活的扩展性&#xff0c;成为解决系统缓存、高并发访问等场景的首选技术之一。在图书管理系统中&…

Jupyter MCP服务器部署实战:AI模型与Python环境无缝集成教程

Jupyter MCP 服务器是基于模型上下文协议&#xff08;Model Context Protocol, MCP&#xff09;的 Jupyter 环境扩展组件&#xff0c;它能够实现大型语言模型与实时编码会话的无缝集成。该服务器通过标准化的协议接口&#xff0c;使 AI 模型能够安全地访问和操作 Jupyter 的核心…

PMO价值重构:从项目管理“交付机器”到“战略推手”

在数字化转型浪潮中&#xff0c;项目管理办公室&#xff08;PMO&#xff09;正经历着前所未有的角色蜕变。传统上&#xff0c;PMO往往被视为项目管理的“交付机器”&#xff0c;专注于项目的按时交付和资源分配。然而&#xff0c;随着企业对战略执行的重视&#xff0c;PMO正逐渐…

零知开源——STM32F407VET6驱动Flappy Bird游戏教程

简介 本教程使用STM32F407VET6零知增强板驱动3.5寸TFT触摸屏实现经典Flappy Bird游戏。通过触摸屏控制小鸟跳跃&#xff0c;躲避障碍物柱体&#xff0c;挑战最高分。项目涉及STM32底层驱动、图形库移植、触摸控制和游戏逻辑设计。 目录 简介 一、硬件准备 二、软件架构 三、…

力扣HOT100之动态规划:300. 最长递增子序列

这道题之前刷代码随想录的时候也刷过&#xff0c;现在又给忘完了。自己尝试着写了一下&#xff0c;发现怎么写都写不对&#xff0c;直接去看视频了。。我自己写的时候的定义是&#xff1a;考虑下标0 ~ i范围内索赔能取到的最长严格递增子序列的长度&#xff0c;后面发现在写递推…

在win10/11下Node.js安装配置教程

下载安装 官网链接https://nodejs.org/zh-cn 下载好以后双击打开&#xff0c;点击下一步 勾选&#xff0c;然后下一步 选择路径、下一步 下一步 配置环境 找到我们安装的文件夹&#xff0c;创建两个文件夹 node_global node_cache 在CMD中配置路径 npm config set p…

飞致云开源社区月度动态报告(2025年5月)

自2023年6月起&#xff0c;中国领先的开源软件公司飞致云以月度为单位发布《飞致云开源社区月度动态报告》&#xff0c;旨在向广大社区用户同步飞致云旗下系列开源软件的发展情况&#xff0c;以及当月主要的产品新版本发布、社区运营成果等相关信息。 飞致云开源运营数据概览&…

压缩包方式在Linux和Windows下安装mongodb

目录 安装流程安装实例1. Linux安装2. Windows安装 总结 安装流程 zip方式安装 优点&#xff1a;自定义性较高&#xff0c;可以自己控制数据、日志等文件的位置 1、下载安装包 2、解压安装包 3、创建各类文件路径 4、配置conf文件 5、使用自定义配置文件启动 安装实例 1. Li…

智慧场馆:科技赋能的艺术盛宴

智慧场馆作为城市公共服务设施数字化转型的典型代表&#xff0c;通过深度融合新一代信息技术&#xff0c;构建起全方位、智能化的运营管理体系。其功能架构不仅提升了场馆本身的运营效能&#xff0c;更重塑了公共服务体验模式&#xff0c;展现出显著的社会价值和商业潜力。 一…

《ChatGPT o3抗命:AI失控警钟还是成长阵痛?》

ChatGPT o3 “抗命” 事件起底 在人工智能的飞速发展进程中&#xff0c;OpenAI 于 2025 年推出的 ChatGPT o3 推理模型&#xff0c;犹如一颗重磅炸弹投入了技术的海洋&#xff0c;激起千层浪。它被视为 “推理模型” 系列的巅峰之作&#xff0c;承载着赋予 ChatGPT 更强大问题解…

【sa-token】 sa-token非 web 上下文无法获取 HttpServletRequest。

Springboot cloud gateway集成sa-token中报错 cn.dev33.satoken.exception.NotWebContextException: 非 web 上下文无法获取 HttpServletRequestat cn.dev33.satoken.spring.SpringMVCUtil.getRequest(SpringMVCUtil.java:45) ~[sa-token-spring-boot-starter-1.38.0.jar:?]官…

多台电脑共用一个ip地址可以吗?会怎么样

在互联网使用日益普及的今天&#xff0c;许多人都面临着多台设备共享网络的需求。一个常见的问题随之而来&#xff1a;多台电脑共用一个IP地址可以吗&#xff1f;这样做会带来哪些影响&#xff1f;本文将深入探讨这一话题。 一、多台电脑共用一个‌IP地址可以吗&#xff1f; 多…

线程(上)【Linux操作系统】

文章目录 线程概念及其相关知识线程的概念及一些重要认识重要认识Linux中线程的实现Linux中的被调度的执行流是被task_struct描述的 线程是如何瓜分进程的代码和数据的&#xff1f;对于数据&#xff1a;对于代码&#xff1a; 线程的优点线程的缺点线程调度细节调度&#xff1a;…