// 權限控制高階組件
export const withAuth = (WrappedComponent) => {
return class extends Component {
componentDidMount() {
this.checkAuth();
}
componentDidUpdate(prevProps) {
if (this.props.location !== prevProps.location) {
this.checkAuth();
}
}
checkAuth = () => {
const token = sessionStorage.getItem('token');
if (!token) {
this.props.history.push('/login');
}
}
render() {
const token = sessionStorage.getItem('token');
return token ? <WrappedComponent {...this.props} /> : null;
}
};
};
// 加載狀態(tài)高階組件
export const withLoading = (WrappedComponent) => {
return class extends Component {
state = {
loading: false
};
setLoading = (loading) => {
this.setState({ loading });
}
render() {
return (
<>
{this.state.loading && <div className="loading-overlay">加載中...</div>}
<WrappedComponent
{...this.props}
setLoading={this.setLoading}
loading={this.state.loading}
/>
</>
);
}
};
};
// 錯誤邊界高階組件
export const withErrorBoundary = (WrappedComponent) => {
return class extends Component {
state = {
hasError: false,
error: null
};
static getDerivedStateFromError(error) {
return {
hasError: true,
error: error
};
}
componentDidCatch(error, errorInfo) {
console.error('Component error:', error, errorInfo);
// 可以在這里添加錯誤上報邏輯
}
render() {
if (this.state.hasError) {
return (
<div className="error-boundary">
<h3>組件渲染出錯</h3>
<p>{this.state.error?.message}</p>
<button onClick={() => this.setState({ hasError: false, error: null })}>
重試
</button>
</div>
);
}
return <WrappedComponent {...this.props} />;
}
};
};
// 數據獲取高階組件
export const withData = (WrappedComponent, dataFetcher) => {
return class extends Component {
state = {
data: null,
loading: false,
error: null
};
componentDidMount() {
this.fetchData();
}
componentDidUpdate(prevProps) {
if (this.shouldRefetch(prevProps)) {
this.fetchData();
}
}
shouldRefetch = (prevProps) => {
// 根據props變化決定是否重新獲取數據
return JSON.stringify(this.props) !== JSON.stringify(prevProps);
}
fetchData = async () => {
this.setState({ loading: true, error: null });
try {
const data = await dataFetcher(this.props);
this.setState({ data, loading: false });
} catch (error) {
this.setState({ error, loading: false });
}
}
render() {
const { data, loading, error } = this.state;
return (
<WrappedComponent
{...this.props}
data={data}
loading={loading}
error={error}
refetch={this.fetchData}
/>
);
}
};
};
// 表單管理高階組件
export const withForm = (WrappedComponent, formConfig) => {
return class extends Component {
state = {
formData: {},
errors: {},
touched: {}
};
handleChange = (field, value) => {
this.setState(prevState => ({
formData: {
...prevState.formData,
[field]: value
},
errors: {
...prevState.errors,
[field]: this.validateField(field, value)
}
}));
};
handleBlur = (field) => {
this.setState(prevState => ({
touched: {
...prevState.touched,
[field]: true
}
}));
};
validateField = (field, value) => {
const rules = formConfig.rules?.[field] || [];
for (const rule of rules) {
const error = rule(value);
if (error) return error;
}
return null;
};
validateForm = () => {
const { formData } = this.state;
const errors = {};
Object.keys(formConfig.rules || {}).forEach(field => {
const error = this.validateField(field, formData[field]);
if (error) errors[field] = error;
});
this.setState({ errors });
return Object.keys(errors).length === 0;
};
resetForm = () => {
this.setState({
formData: {},
errors: {},
touched: {}
});
};
render() {
return (
<WrappedComponent
{...this.props}
formData={this.state.formData}
formErrors={this.state.errors}
formTouched={this.state.touched}
onChange={this.handleChange}
onBlur={this.handleBlur}
validateForm={this.validateForm}
resetForm={this.resetForm}
/>
);
}
};
};
// 函數組合
export const compose = (...funcs) => {
if (funcs.length === 0) return arg => arg;
if (funcs.length === 1) return funcs[0];
return funcs.reduce((a, b) => (...args) => a(b(...args)));
};
// 管道函數
export const pipe = (...funcs) => {
if (funcs.length === 0) return arg => arg;
if (funcs.length === 1) return funcs[0];
return funcs.reduce((a, b) => (...args) => b(a(...args)));
};
// 柯里化函數
export const curry = (fn) => {
const arity = fn.length;
return function curried(...args) {
if (args.length >= arity) {
return fn.apply(this, args);
} else {
return function(...moreArgs) {
return curried.apply(this, args.concat(moreArgs));
};
}
};
};
// 記憶化函數
export const memoize = (fn) => {
const cache = new Map();
return function(...args) {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = fn.apply(this, args);
cache.set(key, result);
return result;
};
};
// 日志裝飾器
export const withLogging = (fn, name = 'Function') => {
return function(...args) {
console.log(`[${name}] Called with:`, args);
const startTime = Date.now();
try {
const result = fn.apply(this, args);
console.log(`[${name}] Completed in ${Date.now() - startTime}ms`);
return result;
} catch (error) {
console.error(`[${name}] Error:`, error);
throw error;
}
};
};
// 重試裝飾器
export const withRetry = (fn, maxRetries = 3, delay = 1000) => {
return async function(...args) {
let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await fn.apply(this, args);
} catch (error) {
lastError = error;
console.warn(`Attempt ${attempt} failed:`, error);
if (attempt < maxRetries) {
await new Promise(resolve => setTimeout(resolve, delay * attempt));
}
}
}
throw lastError;
};
};
// 緩存裝飾器
export const withCache = (fn, ttl = 60000) => { // 默認緩存1分鐘
const cache = new Map();
return function(...args) {
const key = JSON.stringify(args);
const cached = cache.get(key);
if (cached && Date.now() - cached.timestamp < ttl) {
return cached.value;
}
const result = fn.apply(this, args);
cache.set(key, {
value: result,
timestamp: Date.now()
});
return result;
};
};
// 性能監控裝飾器
export const withPerformance = (fn, name = 'Function') => {
return function(...args) {
const start = performance.now();
const result = fn.apply(this, args);
const end = performance.now();
console.log(`[Performance] ${name}: ${(end - start).toFixed(2)}ms`);
return result;
};
};
// 組合多個(gè)高階函數
const enhancedFunction = compose(
withLogging('DataProcessor'),
withRetry(3, 1000),
withCache(30000)
)(processData);
// 管道式組合
const dataPipeline = pipe(
filterInvalidData,
transformDataFormat,
sortByDate,
paginateResults
);
// 柯里化應用
const add = curry((a, b, c) => a + b + c);
const add5 = add(5);
const add5And10 = add5(10);
const result = add5And10(15); // 30
// 裝飾組件
const EnhancedComponent = compose(
withAuth,
withLoading,
withErrorBoundary,
withData(fetchUserData)
)(UserProfile);
// 或者使用裝飾器語(yǔ)法(需要Babel支持)
@withAuth
@withLoading
@withErrorBoundary
@withData(fetchUserData)
class UserProfile extends Component {
// 組件實(shí)現
}
這些高階函數為應用提供了強大的函數組合和組件裝飾能力,支持代碼復用和功能增強。