Vue3 插槽系统详解
1. 默认插槽
重点掌握:
- 插槽的基本概念
- 默认插槽的使用方法
- 后备内容的设置
示例代码:
vue"><!-- BaseCard.vue -->
<template><div class="card"><div class="card-header"><!-- 后备内容 --><slot>默认内容</slot></div></div>
</template><!-- 使用组件 -->
<template><div><!-- 使用默认插槽 --><BaseCard><h2>这是插入到插槽的内容</h2><p>可以插入任意内容</p></BaseCard><!-- 不提供内容时使用后备内容 --><BaseCard /></div>
</template>
2. 具名插槽
重点掌握:
- 多个插槽的命名
- v-slot 指令的使用
- 插槽缩写语法 #
示例代码:
vue"><!-- LayoutComponent.vue -->
<template><div class="layout"><header><slot name="header"></slot></header><main><slot></slot> <!-- 默认插槽 --></main><footer><slot name="footer"></slot></footer></div>
</template><!-- 使用组件 -->
<template><LayoutComponent><!-- 具名插槽使用 --><template v-slot:header><h1>网站标题</h1></template><!-- 默认插槽内容 --><template v-slot:default><p>主要内容区域</p></template><!-- 缩写语法 --><template #footer><p>版权信息 © 2024</p></template></LayoutComponent>
</template>
3. 作用域插槽
重点掌握:
- 插槽数据传递
- 解构插槽 props
- 多个作用域插槽的使用
示例代码:
vue"><!-- DataList.vue -->
<template><div><ul><li v-for="item in items" :key="item.id"><slot name="item" :item="item":index="index":isSelected="selectedId === item.id"><!-- 默认渲染 -->{{ item.name }}</slot></li></ul></div>
</template><script setup>
const props = defineProps({items: {type: Array,required: true}
})const selectedId = ref(null)
</script><!-- 使用组件 -->
<template><DataList :items="users"><!-- 基本用法 --><template v-slot:item="slotProps"><div class="user-item">{{ slotProps.item.name }} ({{ slotProps.index }})</div></template><!-- 使用解构 --><template #item="{ item, index, isSelected }"><div class="user-item" :class="{ 'selected': isSelected }"><h3>{{ item.name }}</h3><p>Position: {{ index + 1 }}</p></div></template></DataList>
</template><!-- 高级用法:表格组件 -->
<template><Table :data="users"><!-- 定义列的渲染方式 --><template #column="{ row }"><td>{{ row.name }}</td></template><!-- 自定义操作列 --><template #actions="{ row }"><button @click="editUser(row)">编辑</button><button @click="deleteUser(row)">删除</button></template></Table>
</template><!-- 实际应用示例:可复用的表单项组件 -->
<!-- FormField.vue -->
<template><div class="form-field"><label :for="id">{{ label }}</label><slot :id="id":value="modelValue":error="error":updateValue="updateValue"></slot><span class="error">{{ error }}</span></div>
</template><!-- 使用表单项组件 -->
<template><form @submit.prevent="onSubmit"><!-- 文本输入 --><FormFieldlabel="用户名"v-model="form.username"><template #default="{ id, value, updateValue, error }"><input:id="id"type="text":value="value"@input="updateValue($event.target.value)":class="{ 'has-error': error }"/></template></FormField><!-- 下拉选择 --><FormFieldlabel="角色"v-model="form.role"><template #default="{ id, value, updateValue }"><select:id="id":value="value"@change="updateValue($event.target.value)"><option value="admin">管理员</option><option value="user">普通用户</option></select></template></FormField></form>
</template>
4. 插槽最佳实践
重点掌握:
- 合理使用默认内容
- 插槽 props 的类型定义
- 动态插槽名的使用
- 性能注意事项
TypeScript 类型定义:
// 定义插槽 props 的类型
type ItemSlotProps = {item: {id: numbername: string[key: string]: any}index: numberisSelected: boolean
}// 组件定义
defineComponent({name: 'DataList',props: {items: {type: Array as PropType<ItemSlotProps['item'][]>,required: true}}
})// 动态插槽名使用
<template><div><slot :name="`column-${columnName}`" v-bind="columnData"></div>
</template>
性能优化:
vue"><!-- 避免不必要的插槽更新 -->
<template><div><slot name="item":item="item"<!-- 使用 memo 避免不必要的更新 -->:memoData="memo(() => expensiveComputation(item))"></slot></div>
</template><script setup>
import { memo } from 'vue'// 缓存计算结果
const memoizedData = memo(() => {return expensiveComputation()
})
</script>
这部分内容详细介绍了Vue3中的三种插槽类型:
- 默认插槽:最基本的内容分发机制
- 具名插槽:通过名字指定内容放置位置
- 作用域插槽:允许子组件向父组件传递数据