首页 React正文

React面试考点总结

景先 React 2018-05-19 213 0

React 的工作原理

React 会创建一个虚拟 DOM(virtual DOM)。当一个组件中的状态改变时,React 首先会通过 “diffing” 算法来标记虚拟 DOM 中的改变,第二步是调节(reconciliation),会用 diff 的结果来更新 DOM。

使用 React 有何优点

  • 只需查看 render 函数就会很容易知道一个组件是如何被渲染的
  • JSX 的引入,使得组件的代码更加可读,也更容易看懂组件的布局,或者组件之间是如何互相引用的
  • 支持服务端渲染,这可以改进 SEO 和性能
  • 易于测试
  • React 只关注 View 层,所以可以和其它任何框架一起使用

区分Real DOM和Virtual DOM

Real DOM Virtual DOM
1. 更新缓慢。 1. 更新更快。
2. 可以直接更新 HTML。 2. 无法直接更新 HTML。
3. 如果元素更新,则创建新DOM。 3. 如果元素更新,则更新 JSX 。
4. DOM操作代价很高。 4. DOM 操作非常简单。
5. 消耗的内存较多。 5. 很少的内存消耗。

展示组件(Presentational component)和容器组件(Container component)之间有何不同

展示组件关心组件看起来是什么。展示专门通过 props 接受数据和回调,并且几乎不会有自身的状态,但当展示组件拥有自身的状态时,通常也只关心 UI 状态而不是数据的状态。

容器组件则更关心组件是如何运作的。容器组件会为展示组件或者其它容器组件提供数据和行为(behavior),它们会调用 Flux actions,并将其作为回调提供给展示组件。容器组件经常是有状态的,因为它们是(其它组件的)数据源。

类组件(Class component)和函数式组件(Functional component)之间有何不同

  • 类组件不仅允许你使用更多额外的功能,如组件自身的状态和生命周期钩子,也能使组件直接访问 store 并维持状态
  • 当组件仅是接收 props,并将组件自身渲染到页面时,该组件就是一个 ‘无状态组件(stateless component)’,可以使用一个纯函数来创建这样的组件。这种组件也被称为哑组件(dumb components)或展示组件

(组件的)状态(state)和属性(props)之间有何不同

State是一种数据结构,用于组件挂载时所需数据的默认值。State 可能会随着时间的推移而发生突变,但多数时候是作为用户事件行为的结果。

Props(properties 的简写)则是组件的配置。props 由父组件传递给子组件,并且就子组件而言,props 是不可变的(immutable)。组件不能改变自身的props,但是可以把其子组件的 props 放在一起(统一管理)。Props 也不仅仅是数据–回调函数也可以通过 props 传递。

React组件生命周期的阶段是什么?

  • 初始渲染阶段:这是组件即将开始其生命之旅并进入 DOM 的阶段。
  • 更新阶段:一旦组件被添加到 DOM,它只有在 prop 或状态发生变化时才可能更新和重新渲染。这些只发生在这个阶段。
  • 卸载阶段:这是组件生命周期的最后阶段,组件被销毁并从 DOM 中删除。

指出(组件)生命周期方法的不同

  • componentWillMount – 多用于根组件中的应用程序配置
  • componentDidMount – 在这可以完成所有没有 DOM 就不能做的所有配置,并开始获取所有你需要的数据;如果需要设置事件监听,也可以在这完成
  • componentWillReceiveProps – 这个周期函数作用于特定的 prop 改变导致的 state 转换
  • shouldComponentUpdate – 如果你担心组件过度渲染,shouldComponentUpdate 是一个改善性能的地方,因为如果组件接收了新的 prop, 它可以阻止(组件)重新渲染。shouldComponentUpdate 应该返回一个布尔值来决定组件是否要重新渲染
  • componentWillUpdate – 很少使用。它可以用于代替组件的 componentWillReceivePropsshouldComponentUpdate(但不能访问之前的 props)
  • componentDidUpdate – 常用于更新 DOM,响应 prop 或 state 的改变
  • componentWillUnmount – 在这你可以取消网络请求,或者移除所有与组件相关的事件监听器

区分状态和 props

条件 State Props
从父组件中接收初始值 Yes Yes
父组件可以改变值 No Yes
在组件中设置默认值 Yes Yes
在组件的内部变化 Yes No
设置子组件的初始值 Yes Yes
在子组件的内部更改 No Yes

如何更新组件的状态

可以用 this.setState()更新组件的状态。

class MyComponent extends React.Component {
    constructor() {
        super();
        this.state = {
            name: 'femans',
            id: '28'
        }
    }
    render()
        {
            setTimeout(()=>{this.setState({name:'tobie', id:'29'})},2000)
            return (              
                <div>
                    <h1>Hello {this.state.name}</h1>
                    <h2>Your Id is {this.state.id}</h2>
                </div>
            );
        }
    }
ReactDOM.render(
    <MyComponent/>, document.getElementById('content')
);

React 组件在何处发起 Ajax 请求

在 React 组件中,应该在 componentDidMount 中发起网络请求。这个方法会在组件第一次“挂载”(被添加到 DOM)时执行,在组件的生命周期中仅会执行一次。更重要的是,你不能保证在组件挂载之前 Ajax 请求已经完成,如果是这样,也就意味着你将尝试在一个未挂载的组件上调用 setState,这将不起作用。在 componentDidMount 中发起网络请求将保证这有一个组件可以更新了。

什么是受控组件(controlled component)

在 HTML 中,类似 <input>, <textarea><select> 这样的表单元素会维护自身的状态,并基于用户的输入来更新。当用户提交表单时,前面提到的元素的值将随表单一起被发送。但在 React 中会有些不同,包含表单元素的组件将会在 state 中追踪输入的值,并且每次调用回调函数时,如 onChange 会更新 state,重新渲染组件。一个输入表单元素,它的值通过 React 的这种方式来控制,这样的元素就被称为”受控元素”。

受控组件VS非受控组件

受控组件 非受控组件
没有维持自己的状态 保持着自己的状态
数据由父组件控制 数据由 DOM 控制
通过 props 获取当前值,然后通过回调通知更改 Refs 用于获取其当前值

在 React 中,refs 的作用是什么

Refs 可以用于获取一个 DOM 节点或者 React 组件的引用。何时使用 refs 的好的示例有管理焦点/文本选择,触发命令动画,或者和第三方 DOM 库集成。你应该避免使用 String 类型的 Refs 和内联的 ref 回调。Refs 回调是 React 所推荐的。

高阶组件(higher order component)

高阶组件是一个以组件为参数并返回一个新组件的函数。HOC 运行你重用代码、逻辑和引导抽象。最常见的可能是 Redux 的 connect 函数。除了简单分享工具库和简单的组合,HOC最好的方式是共享 React 组件之间的行为。如果你发现你在不同的地方写了大量代码来做同一件事时,就应该考虑将代码重构为可重用的 HOC。

使用箭头函数(arrow functions)的优点是什么

  • 作用域安全:在箭头函数之前,每一个新创建的函数都有定义自身的 this 值(在构造函数中是新对象;在严格模式下,函数调用中的 this 是未定义的;如果函数被称为“对象方法”,则为基础对象等),但箭头函数不会,它会使用封闭执行上下文的 this 值。
  • 简单:箭头函数易于阅读和书写
  • 清晰:当一切都是一个箭头函数,任何常规函数都可以立即用于定义作用域。开发者总是可以查找 next-higher 函数语句,以查看 this 的值

为什么建议传递给 setState 的参数是一个 callback 而不是一个对象

因为 this.propsthis.state 的更新可能是异步的,不能依赖它们的值去计算下一个 state

除了在构造函数中绑定 this,还有其它方式吗

可以使用属性初始值设定项(property initializers)来正确绑定回调,create-react-app 也是默认支持的。在回调中你可以使用箭头函数,但问题是每次组件渲染时都会创建一个新的回调。

怎么阻止组件的渲染

在组件的 render 方法中返回 null 并不会影响触发组件的生命周期方法

当渲染一个列表时,何为 key?设置 key 的目的是什么

Keys 会有助于 React 识别哪些 items 改变了,被添加了或者被移除了。Keys 应该被赋予数组内的元素以赋予(DOM)元素一个稳定的标识,选择一个 key 的最佳方法是使用一个字符串,该字符串能惟一地标识一个列表项。很多时候你会使用数据中的 IDs 作为 keys,当你没有稳定的 IDs 用于被渲染的 items 时,可以使用项目索引作为渲染项的 key,但这种方式并不推荐,如果items 可以重新排序,就会导致 re-render 变慢。

super(props)是什么意思?

super() 被调用之前,子类是不能使用 this 的,在 ES2015 中,子类必须在 constructor 中调用 super()。传递 props 给 super() 的原因则是便于(在子类中)能在 constructor 访问 this.props。

JSX简述

JSX 是 JavaScript 语法的一种语法扩展,并拥有 JavaScript 的全部功能。JSX 生产 React “元素”,你可以将任何的 JavaScript 表达式封装在花括号里,然后将其嵌入到 JSX 中。在编译完成之后,JSX 表达式就变成了常规的 JavaScript 对象,这意味着你可以在 if 语句和 for 循环内部使用 JSX,将它赋值给变量,接受它作为参数,并从函数中返回它。

redux

Redux 的基本思想是整个应用的 state 保持在一个单一的 store 中。store 就是一个简单的 javascript 对象,而改变应用 state 的唯一方式是在应用中触发 actions,然后为这些 actions 编写 reducers 来修改 state。整个 state 转化是在 reducers 中完成,并且不应该有任何副作用。

在 Redux 中,何为 store

Store 是一个 javascript 对象,它保存了整个应用的 state。与此同时,Store 也承担以下职责:

  • 允许通过 getState() 访问 state
  • 运行通过 dispatch(action) 改变 state
  • 通过 subscribe(listener) 注册 listeners
  • 通过 subscribe(listener) 返回的函数处理 listeners 的注销

Flux

Flux 是一种强制单向数据流的架构模式。它控制派生数据,并使用具有所有数据权限的中心 store 实现多个组件之间的通信。整个应用中的数据更新必须只能在此处进行。 Flux 为应用提供稳定性并减少运行时的错误。

数据如何通过 Redux 流动?

如何在 Redux 中定义 Action?

React 中的 Action 必须具有 type 属性,该属性指示正在执行的 ACTION 的类型。必须将它们定义为字符串常量,并且还可以向其添加更多的属性。在 Redux 中,action 被名为 Action Creators 的函数所创建。以下是 Action 和Action Creator 的示例:

function addTodo(text) {
       return {
                type: ADD_TODO,    
                 text
    }
}

解释 Reducer 的作用

Reducers 是纯函数,它规定应用程序的状态怎样因响应 ACTION 而改变。Reducers 通过接受先前的状态和 action 来工作,然后它返回一个新的状态。它根据操作的类型确定需要执行哪种更新,然后返回新的值。如果不需要完成任务,它会返回原来的状态。

Store 在 Redux 中的意义是什么?

Store 是一个 JavaScript 对象,它可以保存程序的状态,并提供一些方法来访问状态、调度操作和注册侦听器。应用程序的整个状态/对象树保存在单一存储中。因此,Redux 非常简单且是可预测的。我们可以将中间件传递到 store 来处理数据,并记录改变存储状态的各种操作。所有操作都通过 reducer 返回一个新状态。

Redux与Flux有何不同?

Flux Redux
1. Store 包含状态和更改逻辑 1. Store 和更改逻辑是分开的
2. 有多个 Store 2. 只有一个 Store
3. 所有 Store 都互不影响且是平级的 3. 带有分层
4. 有单一调度器 4. 没有调度器的概念
5. React 组件订阅 store 5. 容器组件是有联系的
6. 状态是可变的 6. 状态是不可改变的

Redux 有哪些优点?

Redux 的优点如下:

  • 结果的可预测性 - 由于总是存在一个真实来源,即 store ,因此不存在如何将当前状态与动作和应用的其他部分同步的问题。
  • 可维护性 - 代码变得更容易维护,具有可预测的结果和严格的结构。
  • 服务器端渲染 - 你只需将服务器上创建的 store 传到客户端即可。这对初始渲染非常有用,并且可以优化应用性能,从而提供更好的用户体验。
  • 开发人员工具 - 从操作到状态更改,开发人员可以实时跟踪应用中发生的所有事情。
  • 社区和生态系统 - Redux 背后有一个巨大的社区,这使得它更加迷人。一个由才华横溢的人组成的大型社区为库的改进做出了贡献,并开发了各种应用。
  • 易于测试 - Redux 的代码主要是小巧、纯粹和独立的功能。这使代码可测试且独立。
  • 组织 - Redux 准确地说明了代码的组织方式,这使得代码在团队使用时更加一致和简单。

什么是React 路由?

React 路由是一个构建在 React 之上的强大的路由库,它有助于向应用程序添加新的屏幕和流。这使 URL 与网页上显示的数据保持同步。它负责维护标准化的结构和行为,并用于开发单页 Web 应用。 React 路由有一个简单的API。

为什么React Router v4中使用 switch 关键字 ?

虽然 <div> 用于封装 Router 中的多个路由,当你想要仅显示要在多个定义的路线中呈现的单个路线时,可以使用 “switch” 关键字。使用时,<switch>标记会按顺序将已定义的 URL 与已定义的路由进行匹配。找到第一个匹配项后,它将渲染指定的路径。从而绕过其它路线。

为什么需要 React 中的路由

Router 用于定义多个路由,当用户定义特定的 URL 时,如果此 URL 与 Router 内定义的任何 “路由” 的路径匹配,则用户将重定向到该特定路由。所以基本上我们需要在自己的应用中添加一个 Router 库,允许创建多个路由,每个路由都会向我们提供一个独特的视图

<switch>
    <route exact path=’/’ component={Home}/>
    <route path=’/posts/:id’ component={Newpost}/>
    <route path=’/posts’   component={Post}/>
</switch>

列出 React Router 的优点。

几个优点是:

1.就像 React 基于组件一样,在 React Router v4 中,API 是 ‘All About Components’。可以将 Router 可视化为单个根组件(<BrowserRouter>),其中我们将特定的子路由(<route>)包起来。
2.无需手动设置历史值:在 React Router v4 中,我们要做的就是将路由包装在 <BrowserRouter> 组件中。
3.包是分开的:共有三个包,分别用于 Web、Native 和 Core。这使我们应用更加紧凑。基于类似的编码风格很容易进行切换。

React Router与常规路由有何不同?

主题 常规路由 React 路由
参与的页面 每个视图对应一个新文件 只涉及单个HTML页面
URL 更改 HTTP 请求被发送到服务器并且接收相应的 HTML 页面 仅更改历史记录属性
体验 用户实际在每个视图的不同页面切换 用户认为自己正在不同的页面间切换
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

评论