React Native 类组件 vs 函数组件 - 面试全面梳

2025-11-18  本文已影响0人  白公子是猫奴

一、核心区别概览

方面 类组件 (Class Components) 函数组件 (Function Components)
定义方式 ES6 Class,继承 React.Component JavaScript 函数
状态管理 this.state + this.setState() useState Hook
生命周期 生命周期方法 useEffect Hook
this 绑定 需要处理 this 绑定问题 this 绑定问题
代码复杂度 相对冗长 更简洁、直观
性能 基本相同(现代React优化后) 基本相同
未来趋势 遗留代码维护 现代开发首选

二、详细对比分析

1. 定义方式和语法

类组件

class Welcome extends React.Component {
  render() {
    return <Text>Hello, {this.props.name}</Text>;
  }
}

函数组件

function Welcome(props) {
  return <Text>Hello, {props.name}</Text>;
}

// 或使用箭头函数
const Welcome = (props) => {
  return <Text>Hello, {props.name}</Text>;
};

面试要点:函数组件语法更简单,更符合函数式编程理念。

2. 状态管理对比

类组件状态

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  increment = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <View>
        <Text>Count: {this.state.count}</Text>
        <Button title="Increment" onPress={this.increment} />
      </View>
    );
  }
}

函数组件状态

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

  const increment = () => {
    setCount(count + 1);
  };

  return (
    <View>
      <Text>Count: {count}</Text>
      <Button title="Increment" onPress={increment} />
    </View>
  );
}

关键区别

3. 生命周期 vs 副作用处理

类组件生命周期

class DataFetcher extends React.Component {
  componentDidMount() {
    // 组件挂载后执行
    this.fetchData();
  }

  componentDidUpdate(prevProps) {
    // 组件更新后执行
    if (prevProps.userId !== this.props.userId) {
      this.fetchData();
    }
  }

  componentWillUnmount() {
    // 组件卸载前执行
    this.cleanup();
  }

  fetchData = async () => {
    const data = await api.getData(this.props.userId);
    this.setState({ data });
  };

  cleanup = () => {
    // 清理工作
  };

  render() {
    return <Text>{this.state.data}</Text>;
  }
}

函数组件副作用

function DataFetcher({ userId }) {
  const [data, setData] = useState(null);

  useEffect(() => {
    // componentDidMount + componentDidUpdate 的组合
    fetchData();
    
    // 返回清理函数 = componentWillUnmount
    return () => {
      cleanup();
    };
  }, [userId]); // 依赖数组,只有 userId 变化时才重新执行

  const fetchData = async () => {
    const result = await api.getData(userId);
    setData(result);
  };

  const cleanup = () => {
    // 清理工作
  };

  return <Text>{data}</Text>;
}

面试要点useEffect 将多个生命周期方法的功能合并,逻辑更集中。

4. this 绑定问题

类组件中的 this 问题

class ProblemComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { clicked: false };
    // 需要手动绑定
    this.handleClick = this.handleClick.bind(this);
  }

  // 或者使用箭头函数避免绑定
  handleClick = () => {
    this.setState({ clicked: true });
  };

  render() {
    return <Button title="Click" onPress={this.handleClick} />;
  }
}

函数组件无 this 问题

function ProblemComponent() {
  const [clicked, setClicked] = useState(false);
  
  const handleClick = () => {
    setClicked(true);
  };

  return <Button title="Click" onPress={handleClick} />;
}

三、Hooks 带来的革命性变化

1. 状态逻辑复用

类组件 - 高阶组件 (HOC)

const withLoading = (WrappedComponent) => {
  return class extends React.Component {
    state = { loading: true };
    
    componentDidMount() {
      // 加载逻辑
      this.setState({ loading: false });
    }
    
    render() {
      return <WrappedComponent loading={this.state.loading} {...this.props} />;
    }
  };
};

函数组件 - 自定义 Hook

// 自定义 Hook
function useLoading() {
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    // 加载逻辑
    setLoading(false);
  }, []);
  
  return loading;
}

// 在多个组件中复用
function ComponentA() {
  const loading = useLoading();
  return loading ? <Text>Loading A...</Text> : <Text>Content A</Text>;
}

function ComponentB() {
  const loading = useLoading();
  return loading ? <Text>Loading B...</Text> : <Text>Content B</Text>;
}

2. 性能优化对比

类组件优化

class ExpensiveComponent extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    return nextProps.value !== this.props.value;
  }
  
  render() {
    return <Text>Value: {this.props.value}</Text>;
  }
}

函数组件优化

const ExpensiveComponent = React.memo(({ value }) => {
  return <Text>Value: {value}</Text>;
});

// 或使用 useMemo, useCallback
function ParentComponent() {
  const [value, setValue] = useState(0);
  
  const expensiveValue = useMemo(() => {
    return computeExpensiveValue(value);
  }, [value]);
  
  const handleClick = useCallback(() => {
    setValue(v => v + 1);
  }, []);
  
  return <ExpensiveComponent value={expensiveValue} onClick={handleClick} />;
}

四、面试常见问题与回答策略

问题1:"为什么React团队推荐使用函数组件?"

结构化回答

  1. 代码简洁性:更少的模板代码,更易理解和维护
  2. 更好的逻辑复用:自定义Hook比HOC/Render Props更直观
  3. 避免 this 绑定问题:减少一类常见的bug来源
  4. 更好的TypeScript支持:类型推断更准确
  5. 未来兼容性:React新特性主要面向函数组件

问题2:"类组件会被完全淘汰吗?"

平衡观点回答
"目前来看,类组件不会立即被完全淘汰,但不推荐在新项目中使用

不过对于新开发的功能,强烈建议使用函数组件+Hooks。"

问题3:"Hooks能完全替代类组件的所有功能吗?"

技术对比回答
"几乎可以,但有少数例外:

实践中,99%的类组件功能都可以用Hocks完美实现。"

问题4:"如何将类组件重构为函数组件?"

方法论回答
"我遵循以下重构步骤:

  1. 保持功能不变:确保重构前后行为一致
  2. 逐项替换
    • this.stateuseState
    • 生命周期方法 → useEffect
    • 实例方法 → 函数组件内的函数
    • this.props → 直接使用props参数
  3. 处理边界情况
    • 使用 useRef 替代实例属性
    • 使用 useImperativeHandle 处理forwardRef
  4. 充分测试:确保所有功能正常工作"

五、现代开发最佳实践

  1. 新项目一律使用函数组件
  2. 逐步迁移重要的类组件
  3. 充分利用自定义Hook抽象业务逻辑
  4. 配合TypeScript获得更好的开发体验

六、面试回答模板

"在React Native开发中,类组件和函数组件是两种主要的组件形式。

类组件是React的传统方式,使用ES6类语法,有完整的生命周期方法和自己的状态管理。它的缺点是代码相对冗长,需要处理this绑定问题。

函数组件是现代React开发的首选,它使用Hooks来处理状态和副作用,代码更简洁直观,逻辑复用能力更强,也没有this绑定问题。

从React 16.8引入Hooks后,函数组件已经能够覆盖类组件的几乎所有使用场景。虽然类组件目前仍然在维护,不会被立即移除,但React团队明确表示新特性会优先面向函数组件开发。

在实际项目中,我会根据团队和项目情况选择:新项目一律使用函数组件+Hooks,对于已有的类组件,只在必要时进行渐进式迁移。"

上一篇 下一篇

猜你喜欢

热点阅读