React组件与props学习笔记

23 阅读9分钟

一、React简介

React是一个用于构建用户界面的JavaScript库,由Facebook(现Meta)开发并维护。它采用声明式编程范式,通过虚拟DOM机制优化性能,并实现了组件化思想,使开发者能够以更模块化的方式构建复杂应用。

React的核心优势在于:

  • 声明式设计:简化UI开发,关注点分离
  • 组件化架构:高度可复用,易于维护
  • 单向数据流:清晰的数据流向,减少状态管理复杂度
  • 跨平台能力:React Native支持移动端开发,无需重学语法
  • 强大的社区生态:丰富的第三方库和工具支持

二、组件基础概念

1. 组件是什么

React组件是UI的构建单元,类似于"乐高积木"。它们可以是函数或类,负责接收输入(props)并返回要渲染的JSX元素。组件封装了特定功能或UI片段,通过组合和嵌套形成复杂的应用界面

2. 组件类型

  • 函数组件:简洁易写,使用箭头函数或function声明
  • 类组件:基于ES6类,使用生命周期方法(逐渐被函数组件替代)
  • 高阶组件:接收组件并返回新组件的工厂函数
  • 渲染道具:通过props传递渲染函数的模式
  • 原生组件:HTML元素如div、span等

3. 组件通信

组件间数据传递遵循单向数据流原则,数据从父组件流向子组件,通过props实现。这种设计使数据流向清晰可预测,简化了状态管理。

4. 组件目录结构

在React项目中,通常将组件组织在特定目录下:

  • components:通用组件
  • pages:页面级组件
  • hooks:自定义hooks
  • styles:样式文件
  • utils:工具函数

这种组织方式有助于保持代码结构清晰,便于维护和扩展。

三、Props的使用与管理

1. Props是什么

Props是"Properties"的缩写,是React组件间传递数据的机制。每个组件都通过props接收来自父组件的数据,props是只读的,子组件不能直接修改props。

2. Props传递方式

// 基本传递
<ChildComponent name="张三" age={25} />

// 动态传递
const user = { name: '李四', age: 30 };
<ChildComponent {...user} />

3. Props解构

函数组件中常用的props解构方式:

// 函数声明方式
function ChildComponent(props) {
  const { name, age } = props;
  // ...
}

// 箭头函数表达式(推荐)
const ChildComponent = ({ name, age }) => {
  // ...
}

现代React开发更推荐使用箭头函数表达式,因为它更简洁,支持参数默认值,且没有this绑定问题 。

4. Props默认值

// 方法1:函数参数默认值(推荐)
const Card = ({ children, className = '' }) => {
  // ...
}

// 方法2:defaultProps属性
Greeting.defaultProps = {
  message: '你好',
  showIcon: false
}

5. Props类型校验

使用prop-types库进行校验:

import PropTypes from 'prop-types';

Greeting.propTypes = {
  // 必填字符串
  name: PropTypes.string.isRequired,

  // 字符串,默认值
  message: PropTypes.string,

  // 布尔值,默认false
  showIcon: {
    type: PropTypes bool,
    default: false
  }
};

6. 动态props传递

// 根据状态动态设置props
function ParentComponent() {
  const [message, setMessage] = useState('初始消息');

  return (
    <div>
      <ChildComponent message={message} />
      <button onClick={() => setMessage('新消息')}>更新消息</button>
    </div>
  );
}

四、组件通信模式

1. 父子组件通信

这是最基础的通信模式,通过props从父组件传递数据到子组件

// 父组件
function Parent() {
  const [data, setData] = useState('初始数据');
  return (
    <div>
      <Child data={data} on数据分析={setData} />
    </div>
  );
}

// 子组件
function Child({ data, on数据分析 }) {
  return (
    <div>
      <p>{data}</p>
      <button onClick={() => on数据分析('新数据')}>更新数据</button>
    </div>
  );
}

2. 兄弟组件通信

通过状态提升(state lifting)实现,将共享状态提升到共同父组件:

// 共同父组件
function Parent() {
  const [sharedData, setSharedData] = useState('');

  return (
    <div>
      <ComponentA send={value => setSharedData(value)} />
      <ComponentB data={sharedData} />
    </div>
  );
}

// 兄弟组件A
const ComponentA = ({ send }) => {
  return <button onClick={() => send('来自A的消息')}>发送</button>;
};

// 兄弟组件B
const ComponentB = ({ data }) => {
  return <p>ComponentB收到:{data}</p>;
};

优点:数据集中管理,逻辑清晰

缺点:父组件容易膨胀,深层组件通信繁琐

3. 跨层级组件通信

对于多层嵌套的组件,可以使用以下方式:

3.1 Context API
// 创建Context
const UserContext = createContext();

// Provider组件
function UserProvider({ children }) {
  const [user, setUser] = useState(null);

  return (
    <UserContext.Provider value={{ user, setUser }}>
      {children}
    </UserContext.Provider>
  );
}

// 使用Context的组件
function Profile() {
  const { user } = useUserContext();

  return <div>用户:{user?.name}</div>;
}

适用场景:需要在多个层级共享的数据,如用户信息、主题设置等

3.2 状态管理库

对于复杂应用,可以使用Redux、Zustand等状态管理库:

// Redux示例
const store = configureStore({
  reducer: {
    user: userReducer
  }
});

function App() {
  return (
    <Provider store={store}>
      <ComponentA />
      <ComponentB />
      <ComponentC />
    </Provider>
  );
}

优点:全局状态管理,避免props drilling

缺点:增加项目复杂度,学习曲线较陡

五、样式管理最佳实践

1. 内联样式

function Card({ children }) {
  const cardStyle = {
    backgroundColor: '#ffffff',
    border-radius: '12px',
    padding: '20px'
  };

  return <div style={cardStyle}>{children}</div>;
}

适用场景:简单组件,需要根据props动态改变样式的场景

优点:与组件逻辑紧密结合,易于动态修改

缺点:样式难以复用,可读性差,维护成本高

2. CSS文件

import './Card.css';

function Card({ children }) {
  return <div className="card>{children}</div>;
}

适用场景:静态样式,需要跨组件复用的场景

优点:样式与组件分离,易于维护和复用

缺点:类名可能冲突,无法直接处理动态样式

3. CSS Modules

import styles from './Card.module.css';

function Card({ children }) {
  return <div className={styles.card}>{children}</div>;
}

工作原理:为类名添加哈希前缀,实现样式作用域化

优点:彻底解决类名冲突问题,样式隔离性强

缺点:需要额外配置,语法稍显复杂

4. CSS-in-JS

import styled from 'styled-components';

const Card = styled.div`
  background-color: #ffffff;
  border-radius: 12px;
  padding: 20px;
  width: 400px;
  max-width: 100%;
  transition: all 0.3s ease;
  overflow: hidden;
  & :hover {
    transform: translateY(-4px);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
  }
`;

适用场景:需要高度动态样式的复杂组件

优点:样式与组件紧密结合,支持动态样式,无需预处理

缺点:可能增加运行时开销,调试稍显困难

六、组件通信最佳实践

1. 优先使用props

对于简单的父子组件通信,props是首选方案,因为它最符合React的设计理念,且实现简单直观 。

2. 状态提升策略

当多个组件需要共享状态时,将状态提升到它们最近的共同父组件

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

  return (
    <div>
      <CounterDisplay count={count} />
      <CounterControl count={count} setCount={setCount} />
    </div>
  );
}

3. 使用Context API

对于需要在多个层级共享的状态,使用Context API

// 创建Context
const ThemeContext = createContext();

// Provider
function App() {
  const [theme, setTheme] = useState('light');

  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      <ComponentA />
      <ComponentB />
    </ThemeContext.Provider>
  );
}

// Consumer
function Header() {
  const { theme } = useThemeContext();

  return (
    <header style={{ background: theme === 'light' ? '#ffffff' : '#333333' }}>
      <Logo />
      <Nav />
    </header>
  );
}

4. 避免props drilling

当组件层级较深时,避免将props逐层传递,可以考虑:

  • 使用Context API
  • 使用状态管理库
  • 重构组件结构,减少层级

5. 使用状态管理库

对于大型复杂应用,考虑使用Redux、Zustand等状态管理库

// Redux示例
const store = configureStore({
  reducer: {
    user: userReducer,
    posts: postsReducer
  }
});

function App() {
  return (
    <Provider store={store}>
      <UserPanel />
      <PostList />
      <CommentForm />
    </Provider>
  );
}

七、React新特性与最佳实践

1. React 19.2新特性

1.1 组件
<Activity mode={活跃 ? 'visible' : 'hidden'}>
  <HeavyComponent />
</Activity>

功能:在组件不可见时保留其状态,但暂停更新,解决条件渲染导致的状态丢失问题

适用场景:多标签页应用、可折叠面板、性能敏感的大型组件

1.2 useEffectEvent
const onConnected = useEffectEvent((data) => {
  // 事件处理逻辑
});

功能:将事件处理逻辑从effect中分离,避免依赖数组的困扰

适用场景:需要在effect中使用事件处理函数,但不想将事件处理函数加入依赖数组的场景

2. 组件开发最佳实践

2.1 组件命名规范
  • 使用PascalCase(大驼峰)命名组件
  • 名称应清晰表达组件功能
  • 避免使用过于通用的名称
2.2 组件参数传递
  • 使用解构赋值简化props访问
  • 对于可选props,设置合理默认值
  • 对于复杂props,使用接口或类型别名定义
const Card = ({ children, className = '' }) => {
  // ...
};

// TypeScript定义
interface CardProps {
  children: ReactNode;
  className?: string;
}
2.3 组件复用策略
  • 高阶组件:接收组件并返回新组件
  • 渲染道具:通过props传递渲染函数
  • 自定义hooks:提取可复用的组件逻辑

3. 样式管理最佳实践

3.1 类名规范
  • 使用BEM命名规范(Block-Element-Modifier)
  • 在JSX中使用className代替class
  • 避免过度嵌套样式
3.2 样式方案选择
样式方案适用场景优点缺点
内联样式简单组件,动态样式与组件逻辑紧密结合,易于动态修改样式难以复用,可读性差
CSS文件静态样式,跨组件复用样式与组件分离,易于维护类名可能冲突,无法直接处理动态样式
CSS Modules需要样式隔离的组件彻底解决类名冲突问题配置复杂,语法稍显繁琐
CSS-in-JS需要高度动态样式的组件支持动态样式,与组件逻辑紧密结合可能增加运行时开销
3.3 样式性能优化
  • 使用CSS预处理器(如Sass、Less)简化样式编写
  • 使用CSS提取工具(如cssnano)优化样式
  • 对于大型应用,考虑使用CSS框架(如Tailwind CSS)

八、学习资源推荐

1. 官方文档

2. 书籍推荐

  • 《React设计原理与实战》:深入理解React核心机制
  • 《深入React:构建现代化Web应用》:全面掌握React开发技巧

3. 实战项目

4. 社区资源

九、总结与展望

1. React核心思想

组件化、声明式、单向数据流是React的核心思想,理解并掌握这些概念对于成为React专家至关重要。

2. 组件通信策略

根据组件关系选择合适的通信方式:

  • 父子组件:props
  • 兄弟组件:状态提升
  • 跨层级组件:Context API
  • 全局状态:状态管理库

3. 样式管理趋势

React样式管理正朝着更模块化、更动态化的方向发展。CSS Modules和CSS-in-JS提供了更好的样式隔离和动态能力,而Tailwind CSS则提供了快速构建UI的工具类方法。

4. React未来发展方向

React Conf 2025展示了React的未来发展方向:

  • 更强大的异步协调能力
  • 更好的性能优化
  • 更完善的生态系统
  • 更友好的开发者体验

随着React技术的不断演进,掌握核心概念和最佳实践将使开发者能够轻松应对各种变化和挑战。

5. 推荐学习路径

对于React新手,推荐以下学习路径:

  1. 掌握React基础概念和组件化思想
  2. 学习props的使用和组件通信模式
  3. 理解并应用状态管理
  4. 探索样式管理的最佳实践
  5. 学习React高级特性和生态系统

通过循序渐进的学习,开发者可以逐步掌握React开发的精髓,构建出高性能、可维护的React应用。