Documentation comments require translating this sentence into English.
Component Development Standards
Component development standards are the foundation for ensuring code maintainability and team collaboration efficiency. Standardized component development includes naming conventions, file structure, code style, and more.
Naming Conventions
Component names should use PascalCase and match the filename. For example, the Button
component should have a filename of Button.jsx
or Button.vue
.
// Correct example
import PrimaryButton from './PrimaryButton';
// Incorrect example
import primaryButton from './primary-button';
File Structure
Each component should reside in its own directory with the following structure:
components/
├── Button/
│ ├── Button.jsx
│ ├── Button.module.css
│ ├── Button.test.js
│ └── index.js
The index.js
file serves as the entry point and should contain:
export { default } from './Button';
Props Definition
Use TypeScript or PropTypes to clearly define component props:
interface ButtonProps {
/**
* Button type
*/
variant?: 'primary' | 'secondary';
/**
* Click event handler
*/
onClick?: () => void;
/**
* Whether the button is disabled
* @default false
*/
disabled?: boolean;
}
function Button({ variant = 'primary', ...props }: ButtonProps) {
// Component implementation
}
Documentation Comment Requirements
Well-documented comments significantly improve code readability and maintainability. Comments should include the component's purpose, props description, example code, and more.
JSDoc Standards
Use standard JSDoc format for comments:
/**
* Generic button component
*
* @example
* <Button variant="primary" onClick={handleClick}>
* Click me
* </Button>
*
* @param {Object} props - Component props
* @param {'primary'|'secondary'} [props.variant='primary'] - Button type
* @param {Function} [props.onClick] - Click event callback
* @param {boolean} [props.disabled=false] - Disabled state
* @returns {React.ReactElement} Button element
*/
function Button(props) {
// Implementation code
}
Props Comment Details
Each prop should include:
- Type description
- Default value (if applicable)
- Optional/required indicator
- Detailed description
interface ModalProps {
/**
* Controls modal visibility
* @default false
*/
visible: boolean;
/**
* Title text. If set to null, the title bar will not be displayed.
*/
title?: string | null;
/**
* Callback when closing. Passing this prop will automatically show a close button.
*/
onClose?: () => void;
}
Complex Component Example
For complex components, provide complete usage examples:
/**
* Data table component
*
* @example
* <DataTable
* columns={[
* { key: 'name', title: 'Name' },
* { key: 'age', title: 'Age', align: 'right' }
* ]}
* data={[
* { id: 1, name: 'John', age: 28 },
* { id: 2, name: 'Jane', age: 32 }
* ]}
* rowKey="id"
* pagination={{
* current: 1,
* pageSize: 10,
* total: 50,
* onChange: handlePageChange
* }}
* />
*/
function DataTable({ columns, data, rowKey, pagination }) {
// Implementation code
}
Code Example Standards
Example code should be functional and avoid oversimplification that could lead to misinterpretation.
Complete Component Example
/**
* Button with loading state
*
* @example
* // Basic usage
* <LoadingButton loading={isLoading} onClick={handleSubmit}>
* Submit
* </LoadingButton>
*
* // Custom loading text
* <LoadingButton
* loading={isLoading}
* loadingText="Processing..."
* >
* Save
* </LoadingButton>
*/
function LoadingButton({
loading = false,
loadingText = 'Loading',
children,
...props
}) {
return (
<button
disabled={loading}
aria-busy={loading}
{...props}
>
{loading ? (
<span className="loading-content">
<Spinner size="small" />
{loadingText}
</span>
) : children}
</button>
);
}
Style File Comments
CSS/Sass/Less files also require comments:
/* Base button styles
* ------------------------ */
.btn {
// Primary button style
&--primary {
background: $color-primary;
// Disabled state
&[disabled] {
opacity: 0.6;
}
}
// Loading state
&.is-loading {
pointer-events: none;
}
}
Type Definition Comments
TypeScript type definitions need detailed explanations:
/**
* Table column configuration
*/
interface TableColumn<T = any> {
/**
* Unique column identifier
*/
key: string;
/**
* Column title
*/
title: React.ReactNode;
/**
* Column width (pixels or percentage)
* @example '100px' | '20%'
*/
width?: string;
/**
* Custom cell rendering
* @param value - Current cell value
* @param record - Entire row data
* @param index - Row index
*/
render?: (value: any, record: T, index: number) => React.ReactNode;
}
Test Case Comments
Test files should describe test scenarios:
describe('Button Component', () => {
/**
* Tests basic rendering
* - Should correctly render children
* - Default style should be primary
*/
it('Basic rendering', () => {
const { getByText } = render(<Button>Test</Button>);
expect(getByText('Test')).toHaveClass('btn-primary');
});
/**
* Tests click behavior
* - Should trigger onClick when clicked
* - Should not trigger when disabled
*/
it('Click behavior', () => {
const handleClick = jest.fn();
const { getByText } = render(
<Button onClick={handleClick}>Clickable</Button>
);
fireEvent.click(getByText('Clickable'));
expect(handleClick).toHaveBeenCalled();
});
});
Documentation Generation
When using tools to auto-generate documentation, note the following:
Storybook Example
export default {
title: 'Components/Button',
component: Button,
parameters: {
// Component description
docs: {
description: {
component: 'A generic button component supporting multiple states and styles',
},
},
},
// Parameter controls
argTypes: {
variant: {
description: 'Button type',
control: {
type: 'select',
options: ['primary', 'secondary', 'danger'],
},
table: {
type: { summary: 'string' },
defaultValue: { summary: 'primary' },
},
},
},
};
const Template = (args) => <Button {...args} />;
// Basic story
export const Primary = Template.bind({});
Primary.args = {
children: 'Primary Button',
};
// Disabled state story
export const Disabled = Template.bind({});
Disabled.args = {
children: 'Disabled Button',
disabled: true,
};
Vue Component Example
Vue SFC component comment standards:
<script>
/**
* File upload component
*
* @displayName FileUploader
* @example
* <file-uploader
* v-model="files"
* accept="image/*"
* multiple
* @error="handleError"
* />
*/
export default {
name: 'FileUploader',
props: {
/**
* Bound value, list of uploaded files
*/
value: {
type: Array,
default: () => []
},
/**
* Accepted file types
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept
*/
accept: {
type: String,
default: '*'
}
},
methods: {
/**
* File selection handler
* @param {Event} event - File input event
* @emits input - Updates v-model
*/
handleChange(event) {
// Method implementation
}
}
}
</script>
Code Review Points
When reviewing components, focus on:
- Whether all props have complete comments
- Whether complex logic has detailed explanations
- Whether example code can run directly
- Whether type definitions are comprehensive
- Whether edge cases are documented
// Example needing improvement
function BadComponent({ data /* Data */ }) {
// Lacks detailed comments
const result = process(data); // Mysterious processing function
return <div>{result}</div>;
}
// Improved version
/**
* Data processing component
*
* @param {Object} props
* @param {Array<{id: number, value: string}>} props.data - Raw data
* Data format requirements:
* - Must include an id field
* - Value field cannot be empty
*/
function GoodComponent({ data }) {
/**
* Processes raw data
* - Filters empty values
* - Sorts by id
* @throws Error when data does not meet requirements
*/
const result = processData(data);
return (
<ul>
{result.map(item => (
<li key={item.id}>{item.value}</li>
))}
</ul>
);
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn