开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情
谈谈你对 React 的了解(必会)
React 是用于构建前端页面的 JavaScript 库。React 主要用于构建 UI,由 Facebook于 2013 年开源。
React 特点 :
- 声明式设计 −React 采用声明范式,可以轻松描述应用
- 高效 −React 通过对 DOM 的模拟,最大限度地减少与 DOM 的交互。
- 灵活 −React 可以与已知的库或框架很好地配合。
- JSX − JSX 是 JavaScript 扩展语法。React 开发不一定使用 JSX, 但我们建议使用它。
- 组件 − 通过 React 构建组件,代码更容易复用,能够很好的应用在大项目的开发中。
- 单向数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。
什么是 JSX?为什么浏览器无法读取 JSX?(必会)
JSX 是 JavaScript XML 的简写,它利用 JavaScript 的表现力和类似 HTML 的模板语法,得 HTML 文件非常容易理解。此文件能使应用非常可靠,并能够提高其性能。浏览器只能处理 JavaScript 对象,而不能读取常规 JavaScript 对象中的 JSX,所以为了使浏览器能够读取 JSX,首先,需要用 Babel 转换器将 JSX 文件转换为 JavaScript 对象,然后再将其传给浏览器
shouldComponentUpdate 是做什么的?(必会)
shouldComponentUpdate 这个方法用来判断是否需要调用 render 方法重新绘制 dom,因为 DOM 的描绘非常消耗性能,如果我们能在 shouldComponentUpdate 方法中能够写出更优化的 dom diff 算法,可以极大的提高性能。
React 性能优化是哪个周期函数?(必会)
shouldComponentUpdate
React 中 keys 的作用是什么?(必会)
Keys 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。
在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染;
此外,React 还需要借助 Key 值来判断元素与本地状态的关联关系,因此我们绝不可忽视转换函数中 Key 的重要性。
React 中 refs 的作用是什么?(必会)
Refs 是 React 提供给我们的安全访问 DOM 元素或者某个组件实例的句柄,我们可以为元素添加 ref 属性然后在回调函数中接受该元素在 DOM 树中的句柄,该值会作为回调函数的第一个参数返回。
请列举 React 中定义组件的方法?(必会)
- 函数式定义的无状态组件
- es6 中 extends React.Component 定义的组件
调用 setState 之后发生了什么?(必会)
- 代码中调用 setState 函数之后,React 会将传入的参数对象与组件当前的状态合并,然后触发所谓的调和过程(Reconciliation)。
- 经过调和过程,React 会以相对高效的方式根据新的状态构建 React 元素树并且着手重新渲染整个 UI 界面;
- 在 React 得到元素树之后,React 会自动计算出新的树与老树的节点差异,然后根据差异对界面进行最小化重渲染;
- 在差异计算算法中,React 能够相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是全部重新渲染。
你怎么理解 redux 的 state 的?(必会)
Store 对象包含所有数据。如果想得到某个时点的数据,就要对 Store 生成快照。这种时点的数据集合,就叫做 State。 当前时刻的 State,可以通过 store.getState() 拿到。唯一改变 state 的方法就是触发 action
除了在构造函数中绑定 this,还有其它方式吗?(必会)
你可以使用属性初始值设定项(property initializers)来正确绑定回调,create-React-app 也是默认支持的。在回调中你可以使用箭头函数,但问题是每次组件渲染时都会创建一个新的回调
(在构造函数中)调用 super(props)的目的是什么?(必会)
在 super() 被调用之前,子类是不能使用 this 的,在 ES2015 中,子类必须在 constructor 中调用 super()。传递 props 给 super() 的原因则是便于(在子类中)能在 constructor 访问 this.props
简述 flux 思想?(必会)
- 用户访问 View
- View 发出用户的 Action
- Dispatcher 收到 Action,要求 Store 进行相应的更新
- Store 更新后,发出一个"change"事件
- View 收到"change"事件后,更新页面
事件在 React 中的处理方式?(必会)
React 元素的事件处理和 DOM 元素类似。但是有一点语法上的不同
- React 事件绑定属性的命名采用驼峰式写法,而不是小写。
- 如果采用 JSX 的语法你需要传入一个函数作为事件处理函数,而不是一个字符串(DOM 元素的写法)
列出 Redux 的核心方法?(必会)
- Action – 这是一个用来描述发生了什么事情的对象
- Reducer – 这是一个确定状态将如何变化的地方
- Store – 整个程序的状态/对象树保存在 Store 中
- View – 只显示 Store 提供的数据
(组件的)状态(state)和属性(props)之间有何不同?(必会)
State 是一种数据结构,用于组件挂载时所需数据的默认值。State 可能会随着时间的推移而发生突变,但多数时候是作为用户事件行为的结果。Props(properties 的简写)则是组件的配置。props 由父组件传递给子组件,并且就子组件而言,props 是不可变的,组件不能改变自身的 props,但是可以把其子组件的 props 放在一起(统一管理)
何为受控组件(controlledcomponent) ?(必会)
在 HTML 中,类似 ,和 这样的表单元素会维护自身的状态,并基于用户的输入来更新,当用户提交表单时,前面提到的元素的值将随表单一起被发送,但在 React中会有些不同,包含表单元素的组件将会在 state 中追踪输入的值,并且每次调用回调函数时,如 onChange 会更新 state,重新渲染组件,一个输入表单元素,它的值通过 React 的这种方式来控制,这样的元素就被称为”受控元素”
何为高阶组件(higherordercomponent) ?(必会)
高阶组件是一个以组件为参数并返回一个新组件的函数。HOC 运行你重用代码、逻辑和引导抽象,最常见的可能是 Redux 的 connect 函数,除了简单分享工具库和简单的组合,HOC 最好的方式是共享 React 组件之间的行为,如果你发现你在不同的地方写了大量代码来做同一件事时,就应该考虑将代码重构为可重用的 HOC
React 中组件如何进行数据传值?(必会)
- 父级传递子级:把数据挂载子组件的属性上,子组件通过 this.props 来接收父组件的数据。
- 子级传递父级:父级需要定义一个修改数据的方法,把修改数据的方法传给子组件,当子组件需要修改父级数据时,调用父级传过来的修改方法
- 兄弟组件传递:属于同一个父级,父组件分别和这两个组件传递。比如子组件 A 操作执行父组件方法,父组件进行修改,然后把信息传给子组件 B
- Context 跨组件传递数据:顶级组件向最里面组件进行传值
解释 Reducer 的作用(必会)
Reducers 是纯函数,它规定应用程序的状态怎样因响应 ACTION 而改变。Reducers 通过接受先前的状态和 action 来工作,然后它返回一个新的状态。它根据操作的类型确定需要执行哪种更新,然后返回新的值。如果不需要完成任务,它会返回原来的状态
redux 有什么缺点(必会)
一个组件所需要的数据,必须由父组件传过来,而不能像 flux 中直接从 store 取;当一个组件相关数据更新时,即使父组件不需要用到这个组件,父组件还是会重新 render,可能会有效率影响,或者需要写复杂的 shouldComponentUpdate 进行判断
了解 redux 么,说一下 redux(必会)
redux 是一个应用数据流框架,主要是解决了组件间状态共享的问题,原理是集中式管理,主要有三个核心方法,action,store,reducer
三大原则:
- 唯一数据源(整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中)
- reducer 必须是纯函数(输入必须对应着唯一的输出)
- State 是只读的, 想要更改必须经过派发 action
Redux 的工作流程
使用通过 reducer 创建出来的 Store 发起一个 Action,reducer 会执行相应的更新 state 的方法,当 state 更新之后,view 会根据 state 做出相应的变化
- 提供 getState()获取到 state
- 通过 dispatch(action)发起 action 更新 state
- 通过 subscribe()注册监听器
vue 和 React 的区别(必会)
监听数据变化的实现原理不同;数据流的不同;React 组合不同功能的方式是通过 HoC(高阶组件),Vue 组合不同功能的方式是通过 mixin;组件通信的不同;模板渲染方式的不同;渲染过程不同等
React 生命周期函数有哪些?(必会)
-
Mounting 挂载阶段
constructor()、componentWillMount()组件挂载到页面之前
render()创建虚拟 DOM,进行 diff 运算,更新 DOM 树。
不可进行 setState()、componentDidMount()组件挂载到页面之后,可以在此请求数据
-
Updateing 更新阶段
componentWillReceiveProps()父级数据发生变化
shouldComponentUpdate()、性能优化
-
Unmounting 卸载阶段
componentWillUnmount 组件卸载和销毁之前立刻停用、可以在此销毁定时器,取消网络请求,消除创建的相关 DOM 节点等
运行阶段生命周期调用顺序?(必会)
运行中阶段可以使用的函数:
- componentWilReceiveProps : 父组件修改属性触发,可以修改新属性、修改状态
- shouldComponentUpdata :返回 false 会阻止 render 调用
- componentWillUpdata :不能修改属性和状态
- render :只能访问 this.props 和 this.state ,只有一个顶层组件,不允许修改状态和 DOM 输出
- componentDidUpdata :可以修改 DOM
React 中 component 和 pureComponent 区别是什么?(必会)
- Component 是 ReactApp 的基本构建的单位,也是 React 中的基本代码复用单位
- PureComponent 与 Component 在除了其 shouldComponentUpdate 方法的实现之外几乎完全相同。
- PureComponent 已经替我们实现了 shouldComponentUpdate 方法。对于 PureComponent 而言,当其 props 或者 state 改变之时,新旧 props 与 state 将进行浅对比(shallow comparison)。另一方面,Component 默认的情况下其 shouldComponentUpdate 方法并不进行新旧 props 与state 的对比
什么是无状态组件,与有状态组件的区别?(必会)
无状态组件主要用来定义模板,接收来自父组件 props 传递过来的数据,使用{props.xxx}的表达式把 props 塞到模板里面
有状态组件主要用来定义交互逻辑和业务数据,使用{this.state.xxx}的表达式把业务数据挂载到容器组件的实例上(有状态组件也可以叫做容器组件,无状态组件也可以叫做展示组件),然后传递 props 到展示组件,展示组件接收到 props,把 props 塞到模板里面
调用 render 时,DOM 一定会更新吗,为什么?(必会)
不一定更新,React 组件中存在两类 DOM,render 函数被调用后,React 会根据 props 或者 state重新创建一棵 virtual DOM 树,虽然每一次调用都重新创建,但因为创建是发生在内存中,所以很快不影响性能。而 virtual dom 的更新并不意味着真实 DOM 的更新,React 采用 diff 算法将 virtualDOM 和真实 DOM 进行比较,找出需要更新的最小的部分,这时 Real DOM 才可能发生修改,所以每次 state 的更改都会使得 render 函数被调用,但是页面 DOM 不一定发生修改
在哪些生命周期中可以修改组件的 state?(必会)
componentDidMount 和 componentDidUpdateconstructor、componentWillMount 中 setState 会发生错误:setState 只能在 mounted 或 mounting组件中执行。componentWillUpdate 中 setState 会导致死循环
connect()前两个参数是什么?(必会)
-
mapStateToProps(state, ownProps)
允 许 我 们 将 store 中 的 数 据 作 为 props 绑 定 到 组 件 中 , 只 要 store 更 新 了 就 会 调 用mapStateToProps 方法,mapStateToProps 返回的结果必须是 object 对象,该对象中的值将会更新到组件中
-
mapDispatchToProps(dispatch, [ownProps])
允许我们将 action 作为 props 绑定到组件中,如果不传这个参数 redux 会把 dispatch 作为属性注入给组件,可以手动当做 store.dispatch 使用 mapDispatchToProps 希望你返回包含对应action 的 object 对象
React-router 的原理(高薪常问)
- BrowserRouter 或 hashRouter 用来渲染 Router 所代表的组件
- Route 用来匹配组件路径并且筛选需要渲染的组件
- Switch 用来筛选需要渲染的唯一组件
- Link 直接渲染某个页面组件
- Redirect 类似于 Link,在没有 Route 匹配成功时触发
React 的 diff 原理(高薪常问)
diff(翻译差异):计算一棵树形结构转换成另一棵树形结构的最少操作
- 把树形结构按照层级分解,只比较同级元素
- 给列表结构的每个单元添加唯一的 key 属性,方便比较
- React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)
- 合并操作,调用 component 的 setState 方法的时候, React 将其标记为 dirty.到每一个事件循环结束, React 检查所有标记 dirty 的 component 重新绘制
- 选择性子树渲染。开发人员可以重写 shouldComponentUpdate 提高 diff 的性能
为什么建议传递给 setState 的参数是一个 callback 而不是一个对象(高薪常问)
因为 this.props 和 this.state 的更新可能是异步的,不能依赖它们的值去计算下一个 state。
redux 中间件原理(高薪常问)
redux 的中间件就是对 store 的 dispatch 做了个升级,升级之后 dispatch 就可以对象和函数都可以接收,这个时候当调用 dispatch 方法给 dispatch 方法传递的参数是一个对象的话,那么 dispatch 就会把这个对象直接传递给 store,跟之前我们写 dispatch 传递给它一个对象没什么区别,但是如果传递给 dispatch 方法是一个函数的话,这个时候 dispatch 已经升级了,它就不会把这个函数直接传递给 store,它会先让这个函数执行,执行完了之后需要调用 store 的时候再去调用 store。所以 dispatch 在这里会根据参数的不同执行不同的事情
React 性能优化的方案(高薪常问)
减少 render 方法的调用; 避免使用状态提升来共享 state,此时应该使用 redux 解决方案; 保持稳定的 dom 结构,尽量避免 dom 节点跨层级移动操作; 使用 css 来隐藏节点,而不是真的移除或添加 DOM 节点等
为什么虚拟 DOM 会提高性能?说下他的原理(高薪常问)
虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom 的 diff 算法避免了没有必要的 dom 操作,从而提高性能
VirtualDOM 工作过程有三个简单的步骤:
- 每当底层数据发生改变时,整个 UI 都将在 VirtualDOM 描述中重新渲染
- 然后计算之前 DOM 表示与新表示的之间的差异
- 完成计算后,将只用实际更改的内容更新 realDOM
setState 何时同步何时异步?(高薪常问)
-
setState 只在合成事件(React 为了解决跨平台,兼容性问题,自己封装了一套事件机制,代理了原生的事件,像在 jsx 中常见的 onClick、onChange 这些都是合成事件)和钩子函数(生命周期)中是“异步”的,在原生事件和 setTimeout 中都是同步的
-
setState 的“异步”并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形式了所谓的“异步”,当然可以通过第二个参数 setState(partialState,callback)中的 callback 拿到更新后的结果
-
setState 的批量更新优化也是建立在“异步”(合成事件、钩子函数)之上的,在原生事件和setTimeout 中不会批量更新,在“异步”中如果对同一个值进行多次 setState ,setState 的批量更新策略会对其进行覆盖,取最后一次的执行,如果是同时 setState 多个不同的值,在更新时会对其进行合并批量更新
祝大家早日找到理想的工作 ,迎娶白富美、出任ceo