2020前端面试真题( React )

JS部分
HTML + CSS
React
Vue
ES6
webpack,node.js,Git等

1.Redux遵循的三个原则是什么?

  1. 单一数据来源:整个应用的状态存储在单个 store 中的对象/状态树里。单一状态树可以更容易地跟踪随时间的变化,并调试或检查应用程序。
  2. 状态是只读的:改变状态的唯一方法是去触发一个动作。动作是描述变化的普通 JS 对象。就像 state 是数据的最小表示一样,该操作是对数据更改的最小表示。
  3. 使用纯函数进行更改:为了指定状态树如何通过操作进行转换,需要用纯函数。纯函数是那些返回值仅取决于其参数值的函数。

2.redux工作流程

首先,UI组件发出 Action。然后,Store 自动调用 Reducer,并且传入两个参数:当前 State 和收到的 Action。 Reducer 会返回新的 State 。State 一旦有变化,Store 就会调用监听函数。用户可以通过store.getState()得到当前状态。

//伪代码,仅供参考
() => store.dispatch({ type: 'CHANGE_VISIBLE' ,payload : text}) //发出Action
//reducer接受并处理数据
const reducer = (state = {
  visible : false,
  attritube : [],
}, action) => {
  switch (action.type) {
    case 'CHANGE_VISIBLE':
      return { ...state, visible: !state.visible , attritube : action.payload }
    default:
      return state
  }
}
//react类组件通过装饰器获取state数据
@connect(state => ({ visible: state.visible , attritube : state.attritube}), dispatch => ({}))
//函数式组件
export default connect((state => ({visible: state.visible , attritube : state.attritube})))('组价名')

3.React 中 key 的作用是什么?

Keys 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。
在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染。此外,React 还需要借助 Key 值来判断元素与本地状态的关联关系。
React中key的使用

4.React生命周期

React生命周期文档
React生命周期图解

  • 常用的React生命周期方法 :
  1. constructor() : 如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数。
    构造函数仅用于以下两种情况:1. 通过给 this.state 赋值对象来初始化内部 state。2.为事件处理函数绑定实例
constructor(props) {
  super(props);
  // 不要在这里调用 this.setState()
  this.state = { counter: 0 };
  this.handleClick = this.handleClick.bind(this);
}
  1. Render() : render() 方法是 class 组件中唯一必须实现的方法。
    render() 函数应该为纯函数,这意味着在不修改组件 state 的情况下,每次调用时都返回相同的结果,并且它不会直接与浏览器交互。

  2. componentDidMount() : 会在组件挂载后(插入 DOM 树中)立即调用。如需通过网络请求获取数据,此处是实例化请求的好地方。可以在 componentDidMount() 里直接调用 setState()。

  3. componentDidUpdate() : componentDidUpdate(prevProps, prevState, snapshot)会在更新后会被立即调用。首次渲染不会执行此方法

  4. componentWillUnmount() : 会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等。componentWillUnmount() 中不应调用 setState(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。

5.vue react 怎么检测数据变化的

  • React
  1. 16年之前可以使用componentWillReveiveProps来监听props的变换。16年之后在最新版本的React中可以使用新出的getDerivedStateFromProps进行props的监听,getDerivedStateFromProps可以返回null或者一个对象,如果是对象,则会更新state
  2. getDerivedStateFromProps的触发条件 : 只要调用setState就会触发getDerivedStateFromProps,并且props的值相同,也会触发getDerivedStateFromProps(16.3版本之后)
  3. 状态变化只能通过setState,调用setState就会更新状态重新渲染dom
  • Vue
  1. vue监听变量变化依靠的是watch

6.React中怎么让setState同步更新?

  1. 回调 : setState函数的第二个参数允许传入回调函数,在状态更新完毕后进行调用,例如下面的这个例子
this.setState({
      data: '666'
    }, () => {
      console.log('加载完成')
    });
  1. promise : 利用promise的特性,可以使用promise封装一个函数去一劳永逸的解决这个问题
setStateAsync(state) {
    return new Promise((resolve) => {
      this.setState(state, resolve)
    });
  }
  1. async+await : 相当于promise的优雅版,我们可以利用await"等一等"的特性去让程序等待await后面的函数做完以后再执行下面的代码(当然,await必须要配合async使用),例如下面的小例子
async myfun(){
await this.setState({
   data: '666'
});
}

7.什么是immutable, 为什么要使用它

  1. Immutable Data 就是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象

  2. Immutable 实现的原理是 Persistent Data Structure (持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变
    TIP:当然,通过这一点,我们可以去做时间旅行,也就是以前调用之前存在过的旧数据。

  3. 同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗, Immutable 使用了 Structural Sharing···· (结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。

            A
          /   \
         A      B
        /  \  /  \
       C   D  E   F 
//例如我们现在数据F发生改变,那么他只会影响到B与A,其他不会受到影响的数据直接复制过来就好了无需重新进行操作,性能有所提升。

在这里插入图片描述

8. 什么是 JSX

JSX是javascript的语法扩展。它就像一个拥有javascript全部功能的模板语言 在里面可以使用js代码
它实现的原理就是react封装了createElement(第一个参数是 标签名,第二个参数是对象 包含了所有的属性,第三个是子节点)。

9. React的diff算法

React Diff 算法的差异查找实质是对两个JavaScript对象(虚拟DOM和真实DOM)的差异查找,所以React更新阶段才会有Diff算法的运用。
更多

10.React中间件(React-thunk , React-promise)

在React种有三个部分 :

(1)Reducer:纯函数,只承担计算 State 的功能,不合适承担其他功能,也承担不了,因为理论上,纯函数不能进行读写操作。

(2)View:与 State 一一对应,可以看作 State 的视觉层,也不合适承担其他功能。

(3)Action:存放数据的对象,即消息的载体,只能被别人操作,自己不能进行任何操作。

而想要在React种异步请求数据,在Action中请求无疑是最完美的。即store.dispatch()方法,可以添加请求数据功能。而中间件就是一个函数,对store.dispatch方法进行了改造,在发出 Action 和执行 Reducer 这两步之间,添加了其他功能。
redux-thunk中间件,改造了store.dispatch,使得后者可以接受函数作为参数。与之相对应的redux-promise返回一个 Promise 对象。
React-thunk的使用

11.装饰器语法

  • 什么是装饰器
   Decorator 是 ES7 的一个新语法,他可以对一些对象进行装饰包装然后返回一个被包装过的对象,
   可以装饰的对象包括:类,属性,方法等。
  • 装饰器的作用
   装饰器的作用就是为已经存在的函数或对象添加额外的功能。 装饰器应用场景及理解: 
   装饰器本质上是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能 。
    这里主要介绍一下类装饰器,使用类装饰器可以减少一些代码的重复编写。
    此时装饰器看起来更像是一个父类,但它又不是一个父类,因为被装饰的类重写一些生命周期函数的时候
    装饰器里面的生命周期函数并不会被覆盖执行。对于componentDidMount 来说,先执被装饰类的
    componentDidMount 再执行 装饰器内的componentDidMount;对于componentWillUnmount 来讲
    先执行装饰器的componentWillUnmount 再执行被装饰的类的componentWillUnmount
装饰器connect实例

关于装饰器的安装及引用在这里并不做赘述,只介绍如何在React中使用装饰器

@connect(state => ({ banner: state.banner}), dispatch => ({
  getBanner() {
    dispatch(getBannerAction)
  },
}))
class PicturesWall extends React.Component {
	componentDidMount() {
    	this.props.getBanner()
  	}
  	//使用 banner 变量
}

在这个类组件中,调用 componentDidMount 生命周期钩子,触发了connect 中的 getBanner 函数,并获取了 redux 中的 banner 变量。在这里 装饰器connect 包裹了 PicturesWall 组件 并触发一个异步函数,将store中的 banner变量传给组件

//函数式组件,换了种写法,作用都一样
const commodityclass = () => {
	...
}
export default connect((state => ({ model_payload: state.model_payload})))(commodityclass)

12.React state 和 props 有什么不同

props 是一个从外部传进组件的参数,主要作为就是从父组件向子组件传递数据,它具有可读性和不变性,只能通过外部组件主动传入新的 props 来重新渲染子组件,否则子组件的 props 以及展现形式不会改变。

state 是组件自身的状态,的主要作用是用于组件保存、控制以及修改自己的状态的一些数据,它只能在 constructor 中初始化,它算是组件的私有属性,不可通过外部访问和修改,只能通过组件内部的 this.setState 来修改,修改 state 属性会导致组件的重新渲染。

  1. state 是组件自己管理数据,控制自己的状态,可变
  2. props 是外部传入的数据参数,不可变

13.React 的路由懒加载怎么实现?

  • 使用传统的 import 的方式。可以在函数内 return 一个 import, 添加 webpackChunkName 的注释,这样 webpack 打包时就会将对应的文件单独打包,当函数执行时再去加载这个包。
    return import( /* webpackChunkName: "lodash" */ 'lodash').then(_ => {}

  • 使用 React.lazy 实现。导入时调用 React.lazy 并给他一个函数参数,函数中返回 import React.lazy(() => import("./XXX"))。配合 Suspense 可以实现在模块未加载完成的时候给用户一个提示。

14.类组件和函数组件有什么区别

类组件可以使用其他特性,如状态 state 和生命周期钩子。

当组件只是接收 props 渲染到页面时,就是无状态组件,就属于函数组件

函数组件的性能比类组件的性能要高, 因为类组件使用的时候要实例化,而函数组件直接执行函数取返回结果即可。为了提高性能,尽量使用函数组件。

函数组件没有this,没有生命周期,没有状态state,
类组件有this,有生命周期,有状态state。

15.什么是高阶组件、受控组件、非受控组件?

高阶组件
是个函数,输出结果是个新组件,可以对输入的组件进行加工,并返回一个具有特定功能的组件。
受控组件
相当于input中的value值通过state值获取,onChange事件改变state中的value值。实现了双向绑定,任意一方的数据发生变化,另一方也会随之改变 。
非受控组件
不需要设置对应的state属性,可通过ref来直接操作真实的dom。

16.vuex和redux的区别

表面区别就是vuex是通过将store注入到组件实例中,通过dispatch和commit来维护state的状态,并可以通过mapstate和this.$store来读取state数据。而redux则是需要通过connect将state和dispatch连接来映射state并操作state。redux没有commit,直接通过dispatch派发一个action来维护state的数据。并且只能通过reducer一个函数来操作state。
rudex使用的是不可变数据;vuex是可变的数据。
rudex每次都是返回一个新的state;而vuex是直接改变state。

17.为什么使用React,React 有那些优势?

  1. React 速度很快:它并不直接对DOM进行操作,而是引入一个叫做虚拟DOM的概念,安插在JavaScript逻辑和实际的DOM之间,所以性能比较好
  2. 跨浏览器兼容:虚拟DOM帮助我们解决了跨浏览器问题,它为我们提供了标准化的API,甚至可以在IE8中使用
  3. 一切都是component:代码更加模块化,重用代码更容易,代码可维护性更高
  4. 单向数据流:Flux 是一个用于在 JavaScript 应用中创建单向数据层的架构,它随着React视图库的开发而被Facebook概念化
  5. 同构、纯粹的JavaScript:因为搜索引擎的爬虫程序依赖的是服务端响应,而不是JavaScript的执行,所以预渲染应用有助于搜索引擎的优化
  6. 兼容性好:比如使用RequireJS来加载和打包,而Browserify和Webpack适用于构建大型应用。他们使得那些艰难的任务变得简单化。

18.为什么有时连续多次setState只有一次生效?

原因就是 React会将存储的多个 setState进行合并 ,如果你想立即使用上次 setState后的结果进行下一次 setState,可以让 setState 接收一个函数而不是一个对象。这个函数用上一个 state 作为第一个参数,将此次更新被应用时的 props 做为第二个参数。

19.redux中sages和thunk中间件的区别,优缺点

redux-thunkredux-saga都是redux的中间件,都是用来处理异步请求的。中间件是指在actionstore之间实现某种功能的函数

使用redux-thunk处理异步等副作用操作,在action中处理异步等副作用操作,此时的action是一个函数,以dispatch,getState作为形参,函数体内的部分可以执行异步。通过redux-thunk来处理异步,action可谓是多种多样,不利于维护。

redux-saga中,action是plain object(原始对象),并且集中处理了所有的异步操作。使用saga,我们生成一个集中处理异步的saga.js文件,

saga优点:
(1)集中处理了所有的异步操作,异步接口部分一目了然
(2)action是普通对象,这跟redux同步的action一模一样
(3)通过Effect,方便异步接口的测试
(4)通过worker 和watcher可以实现非阻塞异步调用,并且同时可以实 现非阻塞调用下的事件监听
(5) 异步操作的流程是可以控制的,可以随时取消相应的异步操作。 redux-saga使用了ES6中的Generator功能,避免了像redux-thunk的回调地狱。

缺点:太复杂,学习成本较高

20.为什么说react是view(视图层)?

• React本身就并不非常认可MVC开发模式
• React被认为是视图层的框架是因为它整个结构就是基于组件的,一切都是组件,然后组件就是渲染页面的基础。
• 不论组件中包含的jsx,methods,state,props,都是属于组件内部的。所以从这个角度看的话,react就是视图层框架。

21.说一下对 纯函数 的理解。

定义:一个函数的返回结果只依赖于它的参数,并且在执行的过程中没有副作用,我们就把该函数称作纯函数。
纯函数的特点 :

  1. 函数的返回结果只依赖于它的参数。
  2. 函数执行过程里面没有副作用。即 函数执行不会对外部变量产生影响
  3. 没有额外的状态依赖。( 指方法内的状态都只在方法的生命周期内存活,这意味着不能在方法内使用共享变量,因为会带来不可知因素。)

纯函数的优点 : 纯函数非常“靠谱”,执行一个纯函数你不用担心它会干什么坏事,它不会产生不可预料的行为,也不会对外部产生影响。不管何时何地,你给它什么它就会乖乖地吐出什么。如果你的应用程序大多数函数都是由纯函数组成,那么你的程序测试、调试起来会非常方便。

22.React性能优化

23.调用 setState 之后发生了什么?

在代码中调用 setState 函数之后,React 会将传入的参数对象与组件当前的状态合并,然后触发所谓的调和过程(Reconciliation)。经过调和过程,React 会以相对高效的方式根据新的状态构建 React 元素树并且着手重新渲染整个 UI 界面。在React 得到元素树之后,React 会自动计算出新的树与老树的节点差异,然后根据差异对界面进行最小化重渲染。在Diff算法中,React 能够相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是全部重新渲染。

24.react中的JSX原理

用 JavaScript 对象来表现一个 DOM 元素的结构JavaScript 写起来太长了,结构看起来又不清晰,用 HTML 的方式写起来就方便很多了。

于是 React.js 就把 JavaScript 的语法扩展了一下,让 JavaScript 语言能够支持这种直接在 JavaScript 代码里面编写类似 HTML 标签结构的语法,这样写起来就方便很多了。编译的过程会把类似 HTML 的 JSX 结构转换成 JavaScript 的对象结构。
React.createElement 会构建一个 JavaScript 对象来描述你 HTML 结构的信息,包括标签名、属性、还有子元素等。
jsx实际上就是一种javascript对象,他经过react语法的构造,还有编译转化,最后得到dom元素,可以插到页面中:所谓的 JSX 其实就是 JavaScript 对象,所以使用 React 和 JSX 的时候一定要经过编译的过程:
JSX —使用react构造组件,bable进行编译—> JavaScript对象 — ReactDOM.render()—>DOM元素 —>插入页面

25.createElement 和 cloneElement 有什么区别?

React.createElement():JSX 语法就是用 React.createElement()来构建 React 元素的。它接受三个参数,第一个参数可以是一个标签名。如 div、span,或者 React 组件。第二个参数为传入的属性。第三个以及之后的参数,皆作为组件的子组件。
React.cloneElement()与 React.createElement()相似,不同的是它传入的第一个参数是一个 React 元素,而不是标签名或组件。新添加的属性会并入原有的属性,传入到返回的新元素中,而旧的子元素将被替换,旧元素的key和ref会保留。

26.React-native性能优化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值