3.7 KiB
Component Guidelines
How components are built in this project.
Overview
This project uses Vue 3 with Element Plus components. Components follow a consistent pattern for props, slots, and composition.
Element Plus el-table-v2 Usage
IMPORTANT: el-table-v2 has a different API than el-table. Key differences:
Auto-resizing with ElAutoResizer
el-table-v2 does NOT have an autosize prop. Use ElAutoResizer wrapper instead:
<el-auto-resizer>
<template #default="{ height, width }">
<el-table-v2
:columns="columns"
:data="data"
:width="width"
:height="height"
:row-height="50"
:header-height="50"
/>
</template>
</el-auto-resizer>
Note: Parent container of ElAutoResizer must have a fixed height (e.g., height: 100% or explicit pixel value).
el-table-v2 Required Props
el-table-v2 requires both width and height as mandatory props - they cannot be omitted.
Slot-to-CellRenderer Conversion
el-table-v2 uses cellRenderer functions instead of Vue slots. To render parent slots:
import { useSlots, renderSlot } from 'vue';
const slots = useSlots();
// In column definition:
col.cellRenderer = ({ cellData, rowData }) => {
if (slots[slotName]) {
return renderSlot(slots, slotName, { row: rowData });
}
return h('span', {}, formattedValue);
};
Column Flex Distribution
For auto-distributed column widths (no explicit width), use flexGrow: 1:
const col = {
key: 'code',
title: 'Name',
dataKey: 'code',
width: 120, // minimum width required
flexGrow: 1, // expands to fill available space
align: 'center',
};
Import Path Conventions
Correct Import Patterns
// ✅ CORRECT: Use relative paths for internal modules
import { clearAndAssign, deepCopy } from "../util/objectUtil";
import { ElAutoResizer, ElTableV2 } from "element-plus";
// ❌ WRONG: noob-mengyxu/utils does not exist
import { clearAndAssign } from "noob-mengyxu/utils";
Rule: For utility functions within the project, always use relative paths (../util/, ./). The noob-mengyxu namespace is only for exporting packages.
Component Structure
<template>
<div class="component-name">
<!-- Markup -->
</div>
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue';
// Props definition
interface Props {
data?: any;
columns?: TableColumn[];
}
const prop = withDefaults(defineProps<Props>(), {
data: () => [],
columns: () => [],
});
const emit = defineEmits(['query', 'change']);
</script>
<style lang="scss" scoped>
/* Scoped styles */
</style>
Props Conventions
- Use
withDefaults(defineProps<Props>())for optional props with defaults - Always provide default values for array/object props
- Use TypeScript interfaces for complex prop types
Common Mistakes
1. Timestamp Formatting Assumptions
The formatStamp function expects Unix timestamps in seconds (not milliseconds):
const formatStamp = (value: any) => {
const date = new Date(value * 1000); // expects seconds
// ...
};
When generating test data, use Math.floor(Date.now() / 1000) or Date.now() / 1000.
2. Element Plus Version Mismatch
Element Plus el-table (v1) and el-table-v2 (virtualized) have completely different APIs:
- v1: uses
propfor columns, slots for cell rendering - v2: uses
columnsprop,cellRendererfunctions, separateElAutoResizer
3. Forgetting Required Props
When using new Element Plus components, verify required props - they will cause runtime errors if omitted.
Accessibility
- Use semantic HTML elements
- Ensure keyboard navigation works
- Add ARIA labels where necessary