看了这篇文章,前端Leader说小伙子组件写的越来越6啦

87 阅读3分钟

image.png
说到前端组件封装,相信各位在工作中一定不陌生,在React应用中,封装组件是一个关键的概念,它有助于将代码模块化、可维护和可重用。以下是一些封装React组件的规范、常用的设计模式和封装原则。

封装规范:

  1. 单一职责原则 (Single Responsibility Principle) :确保组件仅负责一个特定的任务或功能。例如,一个按钮组件只用于呈现按钮,不涉及处理点击事件或状态管理。
  2. 无状态组件 (Functional Components) :使用无状态组件来展示UI,如果不需要组件的状态和生命周期方法。例如:
function Button(props) {
  return <button>{props.label}</button>;
}
  1. 文档化 (Documentation): 为每个组件提供文档,包括用法示例、props的描述和示例。这可以使用注释、JSDoc、或专门的文档工具来完成。

常用的设计模式:

  1. 容器组件与展示组件分离 (Container and Presentational Components)
    将容器组件处理数据和状态,展示组件负责渲染UI。例如:
// 容器组件
class TodoListContainer extends React.Component {
    state = {
      todos: [],
    };

// ... 处理数据和状态的逻辑 ...

    render() {
      return <TodoList todos={this.state.todos} />;
    }
}

// 展示组件
function TodoList(props) {
    return (
      <ul>
        {props.todos.map((todo) => (
          <li key={todo.id}>{todo.text}</li>
        ))}
      </ul>
    );
}

  1. 高阶组件 (Higher-Order Components, HOC)
    创建一个高阶组件,用于共享某种行为或逻辑。例如,一个用于添加日志功能的高阶组件:
function withLogger(WrappedComponent) {
    return class extends React.Component {
      componentDidMount() {
        console.log(`Component ${WrappedComponent.name} mounted.`);
      }

      render() {
        return <WrappedComponent {...this.props} />;
      }
    };
}

// 使用高阶组件
const LogButton = withLogger(Button);

  1. Render Props
    使用一个函数作为children prop,以便子组件可以获取数据或函数。例如,一个鼠标追踪器组件:
import React, { useState } from 'react';

function MouseTracker({ render }) {
    const [mouse, setMouse] = useState({ x: 0, y: 0 });

    const handleMouseMove = (event) => {
      setMouse({ x: event.clientX, y: event.clientY });
    };

    return <div onMouseMove={handleMouseMove}>{render(mouse)}</div>;
}

// 使用Render Props
<MouseTracker
    render={(mouse) => (
      <div>
        Mouse position: ({mouse.x}, {mouse.y})
      </div>
    )}
/>


  1. 自定义Hooks
    创建自定义Hook,用于共享状态逻辑。例如,一个计数器Hook:
import { useState } from 'react';

function useCounter(initialValue = 0) {
    const [count, setCount] = useState(initialValue);

    const increment = () => setCount(count + 1);
    const decrement = () => setCount(count - 1);

    return { count, increment, decrement };
}

  1. Context
    使用React Context来共享数据,特别是在跨多个组件传递相同数据时。例如,主题切换器:
import React, { createContext, useContext, useState } from 'react';

const ThemeContext = createContext();

function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');

  const toggleTheme = () => {
    setTheme(theme === 'light' ? 'dark' : 'light');
  };

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

function useTheme() {
  return useContext(ThemeContext);
}

// 使用Context
function App() {
  const { theme, toggleTheme } = useTheme();

  return (
    <div className={theme}>
      <button onClick={toggleTheme}>Toggle Theme</button>
    </div>
  );
}

封装原则:

  1. DRY原则 (Don't Repeat Yourself)

示例:避免重复的代码。将重复的逻辑抽取成自定义Hook或函数,并在需要的地方使用。例如,一个处理表单输入的自定义Hook:

import { useState } from 'react';

function useFormInput(initialValue) {
  const [value, setValue] = useState(initialValue);

  const handleChange = (e) => {
    setValue(e.target.value);
  };

  return {
    value,
    onChange: handleChange,
  };
}

  1. 组件独立性 (Component Independence)

确保组件不依赖于其他组件的内部状态。每个组件应该是独立的、可测试的单元。

  1. 可配置性 (Configurability)

通过props将组件的行为参数化,以便在不同上下文中进行配置。例如,一个通用的按钮组件可以通过props来设置样式和点击处理函数。

import React from 'react';

function Button({ label, onClick, style }) {
 return (
   <button onClick={onClick} style={style}>
     {label}
   </button>
 );
}

      
  1. 逐层抽象 (Layered Abstraction)

将功能分层,使底层组件专注于基本功能,高层组件用于组合这些功能以实现更复杂的任务。

  1. 性能优化 (Performance Optimization)
    根据需要使用React.memo、shouldComponentUpdate等来避免不必要的渲染。

  2. 错误处理 (Error Handling)
    考虑如何处理组件内的错误,例如使用try/catch块或错误边界(Error Boundaries)。

这些规范、设计模式和封装原则示例有助于编写具有可维护性、可重用性和可测试性的React组件。根据项目的需求和复杂性,选择适当的策略和模式。