项目组件抽离封装思路
核心原则:高内聚低耦合
- 功能独立:每个组件只解决一个特定问题(如按钮、表单、表格)。
- 数据隔离:组件内部状态自管理,通过 props/events 与外部通信。
- 样式封闭:使用 CSS Modules 或 Scoped CSS 避免样式污染。
分层设计
- 基础组件(Button/Input):纯 UI 展示,无业务逻辑。
- 业务组件(OrderTable):组合基础组件,包含业务规则。
- 容器组件(UserDashboard):处理数据流,组合业务组件。
具体代码实现
基础组件封装示例(React)
// components/Button.jsx
import React from 'react';
import styles from './Button.module.css';const Button = ({ children, type = 'primary',onClick
}) => {return (<button className={`${styles.button} ${styles[type]}`}onClick={onClick}>{children}</button>);
};export default Button;
业务组件封装示例(Vue)
<!-- components/UserTable.vue -->
<template><div class="user-table"><el-table :data="users"><el-table-column prop="name" label="姓名" /><el-table-column prop="age" label="年龄" /></el-table></div>
</template><script>
export default {props: {users: {type: Array,required: true}}
};
</script><style scoped>
.user-table {margin: 20px 0;
}
</style>
容器组件示例(React + Redux)
// containers/ProductList.jsx
import { connect } from 'react-redux';
import { fetchProducts } from '../actions';
import ProductCard from '../components/ProductCard';const ProductList = ({ products, loading }) => {useEffect(() => {fetchProducts();}, []);if (loading) return <Spinner />;return (<div className="product-grid">{products.map(product => (<ProductCard key={product.id} {...product} />))}</div>);
};const mapState = state => ({products: state.products.items,loading: state.products.loading
});export default connect(mapState, { fetchProducts })(ProductList);
关键优化策略
Props 设计规范
- 必填参数用
required: true
或 TypeScript 标注 - 默认值通过
default
属性或默认参数设置
// TypeScript 类型定义示例
interface Props {size?: 'small' | 'medium' | 'large';disabled: boolean;
}
跨框架通用方案
- Web Components 实现跨技术栈复用
class MyElement extends HTMLElement {connectedCallback() {this.innerHTML = `<button>Custom Element</button>`;}
}
customElements.define('my-element', MyElement);
文档化辅助
- 使用 Storybook 或 VuePress 生成组件文档
- 添加 JSDoc 注释示例:
/*** 通用分页组件* @param {number} current - 当前页码* @param {number} total - 总页数* @emits {number} change - 页码变更事件*/
常见问题解决方案
样式冲突
- 采用 BEM 命名规范:
block__element--modifier
- CSS-in-JS 方案(styled-components/emotion)
性能优化
- 避免内联函数:
onClick={() => handleClick()}
→onClick={handleClick}
- 复杂组件使用
React.memo
/shouldComponentUpdate
测试方案
- Jest + Testing Library 单元测试
test('Button renders correctly', () => {render(<Button>Test</Button>);expect(screen.getByText('Test')).toBeInTheDocument();
});