当前位置: 首页 > news >正文

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

使用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><MyInputid="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 来自定义错误消息的渲染。

相关文章:

  • 数组题解——最大子数组和​【LeetCode】
  • 流媒体基础解析:音视频封装格式与传输协议
  • 新版智慧景区信息化系统解决方案
  • leetcode216.组合总和III:回溯算法中多条件约束下的状态管理
  • SCSS 全面深度解析
  • C56-亲自实现字符串拷贝函数
  • [学习] RTKlib 实用工具介绍
  • 第六十二节:深度学习-加载 TensorFlow/PyTorch/Caffe 模型
  • MonitorSDK_性能监控(从Web Vital性能指标、PerformanceObserver API和具体代码实现)
  • 3D Gaussian splatting 04: 代码阅读-提取相机位姿和稀疏点云
  • 8086 处理器 Flags 标志位全解析:CPU 的 “晴雨表” 与 “遥控器”总结:
  • 【Docker系列】Docker 容器内安装`ps`命令
  • RFID技术深度剖析:从原理、协议到S50卡与FM17550读写
  • TI MSPM0G3507 简易PID项目显示和按键控制
  • C++语法系列之模板进阶
  • 【C#】一个简单的http服务器项目开发过程详解
  • MySQL备份工具:mysqldump
  • leetcode hot100刷题日记——33.二叉树的层序遍历
  • 单例模式的类和静态方法的类的区别和使用场景
  • Redis实战-基于redis和lua脚本实现分布式锁以及Redission源码解析【万字长文】
  • 公司网站最下面突然有乱码/公司建官网要多少钱
  • wordpress 隐藏后台菜单/苏州排名搜索优化
  • 昆明做网站哪家/英文网站设计公司
  • 山东青岛网站建设公司哪家专业/整站快速排名优化
  • flask做视频网站/个人博客网站设计毕业论文
  • 网站建设应该注意哪些问题/百度推广账号注册