您的位置:

React常见面试题详解

一、React 生命周期

1、生命周期简介

React 生命周期是指 React 组件从实例创建到销毁的整个过程。其中包含挂载、更新和卸载三个阶段。

2、生命周期分类

React 生命周期可以分为三类:Mounting, Updating, Unmounting。其中 Mounting 指组件加载到 DOM 上,Update 指组件数据改变引起的重新渲染,Unmounting 指组件卸载销毁时。

3、常用生命周期

componentDidMount():组件挂载时调用,可以进行 AJAX 请求和 DOM 操作等。

componentDidUpdate():组件更新时调用,可以进行更新操作。

componentWillUnmount():组件卸载时调用,可以进行一些清理操作。

二、React 的虚拟 DOM

1、什么是虚拟 DOM

虚拟 DOM 是简化版的 DOM,是 React 中组件状态改变后重新渲染组件的关键技术。虚拟 DOM 通过一系列的比较和更新操作,尽可能地减少与真实 DOM 的交互,从而提高页面渲染效率。

2、虚拟 DOM 的优点

(1)提高页面渲染效率,避免了每次修改都涉及到真实 DOM 的操作;

(2)简化了操作,提升了开发效率;

(3)实现了 diff 算法,可以最小化更新 DOM,从而提高了页面性能。

三、React 组件间通信

1、组件间通信方式

(1)props 静态方式:通过 props 把数据从父组件传递到子组件。

(2)context 跨级方式:通过 context 属性可以在组件树中直接传递数据,跨级传递更加便捷。

(3)自定义事件方式:通过自定义事件向祖先或子孙组件传递信息。

2、props 与 state 的区别

(1)props 是父组件向子组件传递的数据;state 是组件自己的状态数据。

(2)props 是只读的,不允许子组件修改;state 可以由组件自己修改,但需要通过 setState() 方法改变。

四、React 高阶组件(HOC)

1、高阶组件简介

高阶组件是指将一个组件作为参数,并返回一个新组件的函数。

2、高阶组件的作用

(1)代码复用:将多个组件公用的逻辑抽取成一个高阶组件,避免代码冗余;

(2)扩展组件功能:将某个组件需要的功能通过高阶组件注入的方式进行扩展;

(3)渲染劫持:在不修改组件本身的前提下对组件进行渲染控制。

3、高阶组件示例代码:

  // HOC
  const withLoginStatus = (WrappedComponent) => {
    return class extends React.Component {
      constructor(props) {
        super(props);
        this.state = { isLoggedIn: false };
      }
      componentDidMount() {
        this.setState({ isLoggedIn: true });
      }
      render() {
        const { isLoggedIn } = this.state;
        return ;
      }
    }
  }
  // 组件
  const MyComponent = ({ isLoggedIn }) => (
    

{isLoggedIn ? '您已登录' : '请登录'}

); // 使用 const WrappedComponent = withLoginStatus(MyComponent); ReactDOM.render(, document.getElementById('app'));

五、React 的性能优化

1、虚拟 DOM 优化

(1)减少不必要的渲染:通过 shouldComponentUpdate() 方法来控制是否需要重新渲染组件。

(2)合理使用 React.Fragment:减少多余的 DOM 包裹标签。

(3)使用 key 属性:相同的 key 值可以减少虚拟 DOM 比对时的计算量。

2、其他性能优化

(1)使用 React 生产环境构建:生产环境构建时可以去除开发环境下的调试代码和警告信息。

(2)避免过量渲染:尽可能减少 DOM 操作次数。

(3)优化 JavaScript 代码:避免使用循环嵌套等性能开销大的操作。

代码示例:

  class MyComponent extends React.Component {
    shouldComponentUpdate(nextProps, nextState) {
      if (this.props.text === nextProps.text && this.state.count === nextState.count) {
        return false;
      }
      return true;
    }
    render() {
      return (
        <React.Fragment>
          <span key="text">{this.props.text}</span>
          <button key="btn">{this.state.count}</button>
        </React.Fragment>
      );
    }
  }

六、Redux 与 React 结合

1、Redux 基本用法

(1)Action:定义数据操作的类型。

(2)Reducer:定义数据操作,并返回操作后的新数据。

(3)Store:用于管理应用的 State。

2、Redux 与 React 结合示例代码:

  // Action
  const ADD_TODO = 'ADD_TODO';
  const REMOVE_TODO = 'REMOVE_TODO';

  // Action Creator
  const addTodo = (text) => ({
    type: ADD_TODO,
    payload: {
      text,
    },
  });

  const removeTodo = (id) => ({
    type: REMOVE_TODO,
    payload: {
      id,
    },
  });

  // Reducer
  const todos = (state = [], action) => {
    switch (action.type) {
      case ADD_TODO:
        return [...state, action.payload.text];
      case REMOVE_TODO:
        return state.filter((item, index) => index !== action.payload.id);
      default:
        return state;
    }
  };

  // Store
  const store = createStore(todos);

  // React 组件
  const TodoList = ({ todos }) => (
    <ul>
      {todos.map((item, index) => (
        <li key={index}>{item}</li>
      ))}
    </ul>
  );

  class TodoApp extends React.Component {
    constructor(props) {
      super(props);
      this.state = { todos: store.getState() };
      this.handleAdd = this.handleAdd.bind(this);
      this.handleRemove = this.handleRemove.bind(this);
    }
    componentDidMount() {
      this.unsubscribe = store.subscribe(() => {
        this.setState({ todos: store.getState() });
      });
    }
    componentWillUnmount() {
      this.unsubscribe();
    }
    handleAdd() {
      const text = prompt('请输入待办事项');
      if (text) {
        store.dispatch(addTodo(text));
      }
    }
    handleRemove(index) {
      store.dispatch(removeTodo(index));
    }
    render() {
      const { todos } = this.state;
      return (
        <React.Fragment>
          <TodoList todos={todos} />
          <button onClick={this.handleAdd}>新增</button>
        </React.Fragment>
      );
    }
  }

  ReactDOM.render(<TodoApp />, document.getElementById('app'));