react前端面试题(实时更新)

React前端面试题

1. 对React-Fiber的理解,他解决了什么问题

    react V15在渲染时,会递归比对VirtualDOM树,找出需要变动的节点,然后同步更新他们,一气呵成.这个过程期间,react会间距浏览器资源,这回导致用户触发的时间得不到响应,并且会导致掉帧,导致用户感觉卡顿。
    为了给用户制造一种应用很快的“假象”,不能让一个任务长期霸占着资源。可以将浏览器的渲染、布局、绘制、资源加载(liru HTML解析)、时间相应、脚本执行视作操作题痛的“进程”,需要通过某些调度策略合理地分配CPU资源 从而提高浏览器的用户相应速率,同时兼顾任务执行效率。
    所以React通过Fiber架构,让这个执行过程变成可被中断。“适时”地让出CPU执行权,除了可以让浏览器及时的响应用户的交互,还有其他好处:

  • 分批延迟对DOM及性能操作,避免一次性操作大量DOM节点,可以得到更好的用户体验;
  • 给浏览器一点喘息的机会,他会对代码进行编译优化(JIT)及进行热带吗优化,或者对reflow进行修正。
    核心思想: Fiber 也称协程或者纤程。他和线程并不一样,协程本身是没有并发或者并行能力的(需要配合线程),他只是一种控制流程的让出机制。让出CPU的执行权,让CPU能在这段时间执行其他操作。渲染的过程可以被终端,可以将控制权交回浏览器,让位给高优先级的任务,浏览器空间后再回复渲染。

2.对webSocket的理解

       2.1什么是WebSocket?
**              WebSocket是HTML5下一种新的协议(websocket协议本质上是一个基于tcp的协议)
它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的Websocket是一个持久化的协议

WebSocket原理

    客户端向 WebSocket 服务器通知一个带有所有接收者ID的事件,服务器接收后立即通知所有活跃的客户端,只有ID在接收者ID序列中的客户端才会处理这个事件。

WebSocket特点

  支持双向通信,实时性更强
  可以发送文本,也可以发送二进制数据‘’
  建立在TCP协议之上,服务端的实现比较容易
  数据格式比较轻量,性能开销小,通信高效
  没有同源限制,客户端可以与任意服务器通信
  协议标识符是ws(如果加密,则为wss),服务器网址就是 URL
  与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且  握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

应用场景

  基于websocket的事实通信的特点,其存在的应用场景大概有:
  弹幕
  媒体聊天
  协同编辑
  基于位置的应用
  体育实况更新
  股票基金报价实时更新

4.说说你对koa中洋葱模型的理解?

  4.1什么是洋葱模型。
    Koa的洋葱模型是以next()函数为分割点,先由外到内执行Request的逻辑,然后再由内到外执行Response的逻辑,这里的request的逻辑,我们可以理解为是next之前的内容,response的逻辑是next函数之后的内容,也可以说每一个中间件都有两次处理时机。洋葱模型的核心原理主要是借助compose方法

5.说说package.json中版本号的规则?

major、minor、patch
主版本号、次版本号、修补版本号

patch:修复bug,兼容老版本

minor:新增功能,兼容老版本

major:新的架构调整,不兼容老版本
这三个依赖分别使用了三个符号来表明依赖的版本范围。
*:升级到最新版本
^:升级次版本号和修订号
~:只升级修订号

6.说说React生命周期中有哪些坑?如何避免?

  • getDerivedStateFromProps 容易编写反模式代码,使受控组件和非受控组件区分模糊
  • componentWillMountReact 中已被标记弃用,不推荐使用,主要的原因是因为新的异步架构会导致它被多次调用,所以网络请求以及事件绑定应该放到 componentDidMount
  • componentWillReceiveProps 同样也被标记弃用,被 getDerivedStateFromProps 所取代,主要原因是性能问题。
  • shouldComponentUpdate 通过返回 true 或者 false 来确定是否需要触发新的渲染。主要用于性能优化。
  • componentWillUpdate 同样是由于新的异步渲染机制,而被标记废弃,不推荐使用,原先的逻辑可结合 getSnapshotBeforeUpdatecomponentDidUpdate 改造使用。
    如果在 componentWillUnmount 函数中忘记解除事件绑定,取消定时器等清理操作,容易引发 bug
    如果没有添加错误边界处理,当渲染发生异常时,用户将会看到一个无法操作的白屏,所以一定要添加

7.说说Real diff算法是怎么运作的?

  1. Diff算法是虚拟DOM的一个必然结果,它是通过新旧DOM的对比,将在不更新页面的情况下,将需要内容局部更新
  2. Diff算法遵循深度优先,同层比较的原则
  3. 可以使用key值,可以更加准确的找到DOM节点
    reactdiff算法主要遵循三个层级的策略:
    tree层级
    conponent 层级
    element 层级
    tree层不会做任何修改,如果有不一样,直接删除创建
    component层从父级往子集查找,如果发现不一致,直接删除创建
    element层有key值做比较,如果发现key值可以复用的话,就会将位置进行移动,如果没有,则执行删除创建

8.调和阶段setState干了什么?

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

9.说说redux的实现原理是什么,写出核心代码?

原理

  1. 将应用的状态统一放到state中,由store来管理state
  2. reducer的作用是 返回一个新的state去更新store中对用的state
  3. 按redux的原则,UI层每一次状态的改变都应通过action去触发,action传入对应的reducer 中,reducer返回一个新的state更新store中存放的state,这样就完成了一次状态的更新
  4. subscribe是为store订阅监听函数,这些订阅后的监听函数是在每一次dipatch发起后依次执行
  5. 可以添加中间件对提交的dispatch进行重写
核心API
  6. createStore 创建仓库,接受reducer作为参数
  7. bindActionCreator 绑定store.dispatchaction 的关系
  8. combineReducers 合并多个reducers
  9. applyMiddleware 洋葱模型的中间件,介于dispatchaction之间,重写dispatch
  10. compose 整合多个中间件

10.React合成事件的原理?

  React并不是将click事件绑在该div的真实DOM上,而是在document处监听所有支持的事件,当事件发生并冒泡至document处时,React将事件内容封装并交由真正的处理函数运行。
收集的事件放在dispatchQueue数组中,而冒泡和捕获的区别在于执行时机和顺序,那么我们只需要对数组按照不同顺序循环执行即可
首先会在fiber节点进入render阶段的complete阶段时,将事件监听绑定在root上。然后调用ensureListeningTo进行事件绑定,生成事件合成对象、收集事件、触发真正的事件。
  React 合成事件(SyntheticEvent)是 React 模拟原生 DOM 事件所有能力的一个事件对象,即浏览器原生事件的跨浏览器包装器。它根据 W3C 规范 来定义合成事件,兼容所有浏览器,拥有与浏览器原生事件相同的接口。
将事件绑定在document - v16/容器元素 - v17统一管理,防止很多事件直接绑定在原生的dom元素上。造成一些不可控的情况
  React 想实现一个全浏览器的框架, 为了实现这种目标就需要提供全浏览器一致性的事件系统,以此抹平不同浏览器的差异。

11.React组件之间如何通信?

  1. 父组件向子组件通讯:
    父组件可以向子组件传入props的方式,向子组件进行通讯。
  2. 子组件向父组件通讯:
    props+回调的方式,父组件向子组件传递props进行通讯,此props为作用域为父组件自身的函数,子组件调用该函数,将子组件想要传递的信息,作为参数,传递到⽗组件的作⽤域中。
  3. 兄弟组件通信:
    兄弟组件之间的传递,则父组件作为中间层来实现数据的互通,通过使用父组件传递
    例:组件A – 传值 --> 父组件 – 传值 --> 组件B
  4. 跨层级通讯:
    Context 设计⽬的是为了共享那些对于⼀个
    组件树⽽⾔是“全局”的数据,
    使用context提供了组件之间通讯的一种方式,可以共享数据,其他数据都能读取对应的数据
    例如当前认证的⽤户、主题或⾸选语⾔,对于跨越多层的全局数据通过 Context 通信再适合不过。
  5. 发布订阅者模式:
    发布者发布事件,订阅者监听事件并做出反应,我们可以通过引⼊event模块进⾏通信。
  6. 全局状态管理工具:
    借助Redux或者Mobx等全局状态管理⼯具进⾏通信,这种⼯具会维护⼀个全局状态中⼼Store,并根据不同的事件产⽣新的状态

12.为什么react元素有一个$$type属性?

        目的是为了防止 XSS 攻击。因为 Synbol 无法被序列化,所以 React 可以通过有没有 $$typeof 属性来断出当前的 element 对象是从数据库来的还是自己生成的。如果没有 $$typeof 这个属性,react 会拒绝处理该元素。

13.说说Connect组件的原理是什么?

        connect是一个高阶函数,它真正连接 ReduxReact,包在我们的容器组件的外一层,接收上面 Provider 提供的 store 里面的 statedispatch,传给一个构造函数,返回一个对象,以属性形式传给我们的容器组件。
原理:
    首先传入mapStateToPropsmapDispatchToProps,然后返回一个生产Component的函数(wrapWithConnect),然后再将真正的Component作为参数传入wrapWithConnect,这样就生产出一个经过包裹的Connect组件,该组件具有:
(1)通过props.store获取祖先Componentstore
(2)props包括statePropsdispatchPropsparentProps,合并在一起得到nextState,作为props传给真正的Component
(3)componentDidMount时,添加事件this.store.subscribe(this.handleChange),实现页面交互
(4)shouldComponentUpdate时判断是否有避免进行渲染,提升页面性能,并得到nextState
(5)componentWillUnmount时移除注册的事件this.handleChange
首先connect之所以会成功,是因为Provider组件:

  • 在原应用组件上包裹一层,使原来整个应用成为Provider的子组件,接收Redux的store作为props,通过context对象传递给子孙组件上的connect,它真正连接 Redux 和 React,它包在我们的容器组件的外一层,它接收上面 Provider 提供的 store 里面的 state 和 dispatch,传给一个构造函数,返回一个对象,以属性形式传给我们的容器组件。

14.说说你对redux中间件的理解?常用的中间件有哪些?实现原理?

理解:
     中间件是介于应用系统和系统软件之间的一类软件,它使用系统软件所提供的基础服务(功能),衔接网络上应用系统的各个部分或不同的应用,能够达到资源共享、功能共享的目的
     Redux中,中间件就是放在就是在dispatch过程,在分发action进行拦截处理
     本质上一个函数,对store.dispatch方法进行了改造,在发出 Action和执行 Reducer这两步之间,添加了其他功能
常用中间件:
     redux-thunk:用于异步操作
     redux-logger:用于日志记录
实现原理:
     所有中间件被放进了一个数组chain,然后嵌套执行,最后执行store.dispatch。可以看到,中间件内部(middlewareAPI)可以拿到getStatedispatch这两个方法内部会将dispatch进行一个判断,然后执行对应操作

15.React性能优化的手段有哪些?

  1. 使用纯组件;
  2. 使用 React.memo 进行组件记忆(React.memo 是一个高阶组件),对 于相同的输入,不重复执行;
  3. 如果是类组件,使用 shouldComponentUpdate(这是在重新渲染组件之前触发的其中一个生命周期事件)生命周期事件,可以利用此事件来决定何时需要重新渲染组件;
  4. 路由懒加载;
  5. 使用 React Fragments 避免额外标记;
  6. 不要使用内联函数定义(如果我们使用内联函数,则每次调用“render”函数时都会创建一个新的函数实例);
  7. 避免在Willxxx系列的生命周期中进行异步请求,操作dom等;
  8. 如果是类组件,事件函数在Constructor中绑定bind改变this指向;
  9. 避免使用内联样式属性;
  10. 优化 React 中的条件渲染;
  11. 不要在 render 方法中导出数据;
  12. 列表渲染的时候加key
  13. 在函数组件中使用useCallbackuseMemo来进行组件优化,依赖没有变化的话,不重复执行;
  14. 类组件中使用immutable对象;

16.说说你对事件循环event loop的理解?

     任务在主线程不断进栈出栈的一个循环过程。任务会在将要执行时进入主线程,在执行完毕后会退出主线程。
     JavaScript是一门单线程的语言,意味着同一时间内只能做一件事,
但是这并不意味着单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环
在JavaScript中,所有的任务都可以分为
     同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行
     异步任务:异步执行的任务,比如ajax网络请求,setTimeout定时函数等
     异步任务还可以细分为微任务与宏任务
     微任务一个需要异步执行的函数,执行时机是在主函数执行结束之后、当前宏任务结束之前
     宏任务的时间粒度比较大,执行的时间间隔是不能精确控制的,对一些高实时性的需求就不太符合

17.前端跨域的解决方案?

一、什么是跨域?
     在前端领域中,跨域是指浏览器允许向服务器发送跨域请求,从而克服Ajax只能同源使用的限制。
二、什么是同源策略?
     同源策略是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
同源策略限制以下几种行为:
     Cookie、LocalStorage 和 IndexDB 无法读取
     DOM和JS对象无法获得
     AJAX 请求不能发送
三、9种跨域解决方案
1、JSONP跨域
2、跨域资源共享(CORS)
3、nginx代理跨域
4、nodejs中间件代理跨域
5、document.domain+ iframe跨域
6、location.hash + iframe跨域
7、window.name + iframe跨域
8、postMessage跨域
9、WebSocket协议跨域

小结
  以上就是9种常见的跨域解决方案,jsonp(只支持get请求,支持老的IE浏览器)适合加载不同域名的js、css,img等静态资源;CORS(支持所有类型的HTTP请求,但浏览器IE10以下不支持)适合做ajax各种跨域请求;Nginx代理跨域和nodejs中间件跨域原理都相似,都是搭建一个服务器,直接在服务器端请求HTTP接口,这适合前后端分离的前端项目调后端接口。document.domain+iframe适合主域名相同,子域名不同的跨域请求。postMessage、websocket都是HTML5新特性,兼容性不是很好,只适用于主流浏览器和IE10+。

18.数组常用方法及作用,至少15个?

  1. Array.length:返回或设置一个数组中的元素个数
  2. Array.from() :对伪数组或可迭代对象(包括arguments,Array,Map,Set,String…)转换成数组对象
  3. Array.isArray():用于确定传递的值是否是一个 Array
  4. concat():方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
  5. every(callback):方法测试数组的所有元素是否都通过了指定函数的测试
  6. filter():创建一个新数组, 其包含通过所提供函数实现的测试的所有元素
  7. find():返回数组中满足提供的测试函数的第一个元素的值
  8. forEach():方法对数组的每个元素执行一次提供的函数
  9. includes():用来判断一个数组是否包含一个指定的值,如果是,酌情返回 truefalse
  10. indexOf():返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1
  11. join():将数组(或一个类数组对象)的所有元素连接到一个字符串中
  12. lastIndexOf():返回指定元素(也即有效的 JavaScript 值或变量)在数组中的最后一个的索引,如果 不存在则返回 -1。从数组的后面向前查找
  13. map():创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果
  14. pop():从数组中删除最后一个元素,并返回该元素的值。此方法更改数组的长度
  15. push():将一个或多个元素添加到数组的末尾
  16. reduce():累加器和数组中的每个元素(从左到右)应用一个函数
  17. shift():从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度
  18. slice():返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对象
  19. some():测试数组中的某些元素是否通过由提供的函数实现的测试。
  20. sort():当的位置对数组的元素进行排序,并返回数组。
  21. splice():通过删除现有元素和/或添加新元素来更改一个数组的内容
  22. toString():返回一个字符串,表示指定的数组及其元素
  23. unshift():将一个或多个元素添加到数组的开头,并返回新数组的长度
  24. toLocaleString():返回一个字符串表示数组中的元素。数组中的元素将使用各自的 toLocaleString 方法转成字符串,这些字符串将使用一个特定语言环境的字符串(例如一个逗号 “,”)隔开

19.React render方法的原理,在什么时候会触发?

原理:
     在类组件中render函数指的就是render方法;而在函数组件中,指的就是整个函数组件
     render函数中的jsx语句会被编译成我们熟悉的js代码,在render过程中,react将新调用的render函数返回的树与旧版本的树进行比较,这一步是决定如何更新 DOM 的必要步骤,然后进行 diff 比较,更新dom树
触发机:
     类组件调用 setState 修改状态
     函数组件通过useState hook修改状态
     一旦执行了setState就会执行render方法,useState 会判断当前值有无发生改变确定是否执行render方法,一旦父组件发生渲染,子组件也会渲染

20.说说你对vue中mixin的理解?

     mixin是一种类,在vue中就是js文件,主要的作用是作为功能模块引用。因为在项目中,可能不同组件会有相同的功能,比如控制元素的显示和隐藏,如果他们的变量和规则也完全相同的话,就可以把这个功能单独提取出来,放在mixin.js中,再引入,就可以实现一样的功能了。引入的方法也分为全局混入和局部混入,局部混入就是在每个组件中引入,全局混入就是在main.js中通过Vue.mixin()引入。

21.for…in循环和for…of循环的区别?

for...in 循环:只能获得对象的键名,不能获得键值
for…in循环有几个缺点
  ①数组的键名是数字,但是for…in循环是以字符串作为键名“0”、“1”、“2”等等。
  ②for…in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。
  ③某些情况下,for…in循环会以任意顺序遍历键名。
  for…in循环主要是为遍历对象而设计的,不适用于遍历数组。
  
for...of 循环:允许遍历获得键值
for…of循环
  ①有着同for…in一样的简洁语法,但是没有for…in那些缺点。
  ②不同于forEach方法,它可以与breakcontinuereturn配合使用。
  ③提供了遍历所有数据结构的统一操作接口

22.Js数据类型判断都有哪几种方式?至少说出5种?它们的区别是什么?

1. typeof判断
typeof返回的类型都是字符串形式
2. Constructor
实例constructor属性指向构造函数本身
constructor 判断方法跟instanceof相似,但是constructor检测Objectinstanceof不一样,constructor还可以处理基本数据类型的检测,不仅仅是对象类型
3. Instanceof
instanceof可以判类型是否是实例的构造函数
instanceof 后面一定要是对象类型,并且大小写不能错,该方法适合一些条件选择或分支。
4. Object.prototype.toString.call()
判断类型的原型对象是否在某个对象的原型链上
5. 通过object原型上的方法判断
比如array.isArray()来判断是不是一个数组
6. ===(严格运算符)
通常出现在我们的条件判断中,用来判断数据类型的话就会非常的有局限性,比如判断一个变量是否为空,变量是否为数据等

23.说说你对Object.defineProperty()的理解?

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
该方法接受三个参数

  • 第一个参数是 obj:要定义属性的对象,
  • 第二个参数是 prop:要定义或修改的属性的名称或 Symbol
  • 第三个参数是 descriptor:要定义或修改的属性描述符
    函数的第三个参数 descriptor 所表示的属性描述符有两种形式:数据描述符存取描述符
  • 数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。
  • 存取描述符是由 getter 函数和 setter 函数所描述的属性。
    一个描述符只能是这两者其中之一;不能同时是两者。
    这两种同时拥有下列两种键值:
    configurable 是否可以删除目标属性或是否可以再次修改属性的特性(writable, configurable, enumerable)。设置为true可以被删除或可以重新设置特性;设置为false,不能被可以被删除或不可以重新设置特性。默认为false
    enumerable 当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。默认为 false

24.props和state相同点和不同点??

不同点:
1.props不可以在组件内部修改,但state可以在组件内部修改
2.可以从父组件修改自组件的props,而不能从父组件修改自组件的state
相同点:
1.props和state都是导出HTML的原始数据。
2.props和state都是确定性的,如果我们写的组件为同一props和state的组合生成了不同的输出,那木我们肯定在哪里做错了
4.props和state都会触发渲染更新
5.props和state都是纯JS对象(用typeof来判断,结果都是object)
6.可以从父组件得到初始值props和state的初始值

25.shouldComponentUpdate有什么作用?

shouldComponentUpdate () 的返回值用于判断 React 组件的输出是否受当前 state 或 props 更改的影响,当 props 或 state 发生变化时,shouldComponentUpdate () 会在渲染执行之前被调用。

26.说说React生命周期有哪些不同的阶段?每个阶段对应的方法是?

(1)挂载阶段:
constructor() 在 React 组件挂载之前,会调用它的构造函数。
componentWillMount: 在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。
componentDidMount(): 在组件挂载后(插入 DOM 树中)立即调用
(2)更新运行阶段:
componentWillReceiveProps: 在接受父组件改变后的props需要重新渲染组件时用到的比较多,外部组件传递频繁的时候会导致效率比较低
shouldComponentUpdate():用于控制组件重新渲染的生命周期,state发生变化,组件会进入重新渲染的流程,在这里return false可以阻止组件的更新
render(): render() 方法是 class 组件中唯一必须实现的方法。
componentWillUpdate()*: shouldComponentUpdate返回true以后,组件进入重新渲染完成之前进入这个函数。
componentDidUpdate(): 每次state改变并重新渲染页面后都会进入这个生命周期
(3)卸载或销毁阶段:
componentWillUnmount (): 在此处完成组件的卸载和数据的销毁。

27.什么是强缓存和协商缓存?

27.1 浏览器缓存(Brower Caching):

是浏览器对之前请求过的文件进行缓存,以便下一次访问时重复使用,节省带宽,提高访问速度,降低服务器压力 HTTP 1.0协议中的。简而言之,就 是告诉浏览器在约定的这个时间前,可以直接从缓存中获取资源而无需跑到服务器去获取。 http缓存机制主要在http响应头中设定,响应头中相关字段为Expires、Cache-Control、Last-Modified、Etag

27.2强缓存:

浏览器不会像服务器发送任何请求,直接从本地缓存中读取文件并返回Status Code: 200 OK

27.3协商缓存
协商缓存: 向服务器发送请求,服务器会根据这个请求的request header的一些参数来判断是否命中协商缓存,如果命中,则返回304状态码并带上新的response header通知浏览器从缓存中读取资源;

28.说说react 中jsx语法糖的本质?

     jsx是JavaScript的一种语法扩展,它跟模板语言很接近,但是它充分具备JavaScript的能力
JSX就是用来声明React当中的元素,React使用JSX来描述用户界面
JSX语法糖允许前端开发者使用我们最熟悉的类HTML标签语法来创建虚拟DOM在降低学习成本

29.说说AMD、CMD、commonJS模块化规范的区别?

      CommonJS用同步的方式加载模块。在服务端,模块文件都存放在本地磁盘,读取非常快,所以这样做不会有问题。但是在浏览器端,限于网络原因,更合理的方案是使用异步加载。
AMD规范采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行
CMD是另一种js模块化方案,它与AMD很类似,不同点在于:AMD推崇依赖前置、提前执行,CMD推崇依赖就近、延迟执行

30.Vue中自定义指令的理解,应用场景有哪些?

      指令系统是计算机硬件的语言系统,也叫机器语言,它是系统程序员看到的计算机的主要属性。因此指令系统表征了计算机的基本功能决定了机器所要求的能力
注册一个自定义指令有全局注册与局部注册
全局注册主要是通过Vue.directive方法进行注册
Vue.directive第一个参数是指令的名字(不需要写上v-前缀),第二个参数可以是对象数据,也可以是一个指令函数
局注册通过在组件options选项中设置directive属性
然后你可以在模板中任何元素上使用新的 v-focus property,如下:

  • 表单防止重复提交
  • 图片懒加载
  • 一键 Copy的功能
  • 拖拽指令、
  • 页面水印、
  • 权限校验

31.大文件如何做断点续传?

分片传

  1. 将需要上传的文件按照一定的分割规则,分割成相同大小的数据块;
  2. 初始化一个分片上传任务,返回本次分片上传唯一标识;
  3. 按照一定的策略(串行或并行)发送各个分片数据块;
  4. 发送完成后,服务端根据判断数据上传是否完整,如果完整,则进行数据块合成得到原始文件
    断电续传
    断点续传指的是在下载或上传时,将下载或上传任务人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上传下载未完成的部分,而没有必要从头开始上传下载。用户可以节省时间,提高速度

32.说说你对koa中洋葱模型的理解?

      Koa 的洋葱模型指的是以 next() 函数为分割点,先由外到内执行 Request 的逻辑,再由内到外执行 Response 的逻辑。通过洋葱模型,将多个中间件之间通信等变得更加可行和简单
在洋葱模型中,每一层相当于一个中间件,用来处理特定的功能, 也就是说每一个中间件都有两次处理时机

33.react新出来两个钩子函数是什么?和删掉的will系列有什么区别

      新生命周期中新增了两个钩子,分别为getDerivedStateFromProps(从props中得到衍生的state)和getSnapshotBeforeUpdate。
区别
1、componentWillMount中可能需要做的事(一些数据初始化的操作就应该放在这个钩子中处理),constructor与componentDidMount也能做,甚至做的更好,此方法被废弃。
2、componentWillReceiveProps实际行为与命名并不相符,由于不稳定性已由getDerivedStateFromProps代替;
3、而componentWillUpdate同等理由被getSnapshotBeforeUpdate代替

34.在虚拟dom计算的时候diff和key之间有什么关系?

      key 当同一层级的某个节点添加了对于其他同级节点唯一的key属性,当它在当前层级的位置发生了变化后。react diff算法通过新旧节点比较后,如果发现了key值相同的新旧节点,就会执行移动操作(然后依然按原策略深入节点内部的差异对比更新),而不会执行原策略的删除旧节点,创建新节点的操作。

35. withRouter的作用?

     把不是通过路由切换过来的组件中,将react-router 的 history、location、match 三个对象传入props对象上
     不是所有组件都直接与路由相连(比如拆分的子组件)的,当这些组件需要路由参数时,使用withRouter就可以给此组件传入路由参数,将react-router的history、location、match三个对象传入props对象上,此时就可以使用this.props.history跳转页面了或者接受参数了

36.React的props.children使用map函数来遍历会收到异常显示,为什么?应该 如何遍历?

在reactJS中props.children不一定是数组
有三种可能 :
     1当前组件没有子节点数据类型就是undefined,
     2有一个子节点数据类型就是object 。
     3 有多个子节点的时候才会是array ,只有在多个节点的时候才可以直接调用map方法,react资深提供了一个react.children.map()方法,可以安全遍历子节点对象。

37.谈谈你对immutable.js的理解?

     Immutable.js采用了 持久化数据结构 ,保证每一个对象都是不可变的,任何添加、修改、删除等操作都会生成一个新的对象,且通过 结构共享 等方式大幅提高性能

38.redux中同步action与异步action最大的区别是什么?

     同步: Redux的教程中反复使用todo列表的例子,那就是个典型的同步action,每当disptach action时,state就会被立即更新[当然setState是异步的]
     异步: 一般异步处理都会使用中间件,比如redux-thunk或者redux-saga,他们做的事情是包装dispatch,request action由view触发,receive action由这些中间件触发

39.redux-saga和redux-thunk的区别与使用场景?

redux-thunk:通过执行action中的函数实现业务逻辑,没有拓展API
redux-saga:通过定义saga函数进行监控,同时提供一些常用的API
redux-thunk将部分异步处理业务逻辑写在action中,redux-sagasaga则是放在监控的函数中。

40.CDN的特点及意义?

DN的功能特点:

(1)节省骨干网带宽,减少带宽需求量;
(2)提供服务器端加速,解决由于用户访问量大造成的服务器过载问题;
(3)服务商能使用Web
Cache技术在本地缓存用户访问过的Web页面和对象,实现相同对象的访问无须占用主干的出口带宽,并提高用户访问因特网页面的相应时间的需求;
(4)能克服网站分布不均的问题,并且能降低网站自身建设和维护成本;
(5)降低“通信风暴”的影响,提高网络访问的稳定性

意义
      使用CDN可以获取一些好处,无论它们是公有CDN还是提供静态内容的私有CDN,你的里程可能会有所不同,具体取决于通过CDN传递的流量以及你产生的流量。

41.谈谈你对react的理解,他有哪些特性

     React,用于构建用户界面的 JavaScript 库,提供了 UI 层面的解决方案
遵循组件设计模式、声明式编程范式和函数式编程概念,以使前端应用程序更高效
使用虚拟DOM来有效地操作DOM,遵循从高阶组件到低阶组件的单向数据流
帮助我们将界面成了各个独立的小块,每一个块就是组件,这些组件之间可以组合、嵌套,构成整体页面
     react 类组件使用一个名为 render() 的方法或者函数组件return,接收输入的数据并返回需要展示的内容
特性
React特性有很多,如:
JSX语法
单向数据绑定
虚拟DOM
声明式编程
Component

42.Vue组件通信?

1.父组件通过 props 向子组件传递数据,子组件通过 e m i t 和父组件通信 2. r e f :这个属性用在子组件上,指向子组件的实例,可以通过实例来访问组件的数据和方法 3. emit 和父组件通信 2.ref:这个属性用在子组件上,指向子组件的实例,可以通过实例来访问组件的数据和方法 3. emit和父组件通信2.ref:这个属性用在子组件上,指向子组件的实例,可以通过实例来访问组件的数据和方法3.emit 绑定一个自定义事件,当这个事件被执行的时候就会将参数传递给父组件,而父组件通过v-on监听并接收参数
4.eventBus事件总线($emit / $on)

43.说说你对vuex的理解?写出其原理的核心代码?

     Vuex采用MVC模式中的Model层,规定所有的数据必须通过action—>mutaion—>state这个流程进行来改变状态的。再结合Vue的数据视图双向绑定实现页面的更新。统一页面状态管理,可以让复杂的组件交互变的简单清晰,同时在调试时也可以通过DEVtools去查看状态

44.函数组件中如何使用useReducer

创建初始值的状态initialState
创建所有对状态的操作reducer(state,action)
传给useReducer,得到读和写的接口
调用写({‘type’:‘操作类型’})
useReducer 接受的第一个参数是一个函数,我们可以认为它就是一个 reducer , reducer 的参数就是常规 reducer 里面的 stateaction ,返回改变后的 state , useReducer 第二个参数为 state 的初始值 返回一个数组,数组的第一项就是更新之后 state 的值 ,第二个参数是派发更新的 dispatch 函数。

45.说说你对高阶组件的理解?应用场景有哪些?

如果一个函数 接受一个或多个函数作为参数或者返回一个函数 就可称之为 高阶函数。
什么是React高阶组件:一个组件的参数是组件,并且返回值是一个组件,我们称这类组件为高阶组件
withRouter() memo() react-redux中connect方法是高阶组件

46.节流防抖的区别是什么,具体解释一下?

防抖:
1.当事件触发时,相应的函数并不会立即触发,而是会等待一定的时间(非常短的时间);
2.当事件密集触发时,函数的触发会被频繁的推迟;
3.只有等待了一段时间也没有事件触发,才会真正的执行响应函数;

function debounce(func, wait) {
    let timeout;
    return function () {
        let context = this; // 保存this指向
        let args = arguments; // 拿到event对象
        clearTimeout(timeout)
        timeout = setTimeout(function(){
            func.apply(context, args)
        }, wait);
    }
}

节流:
1.当事件触发时,会执行这个事件的响应函数;
2.如果这个事件会被频繁触发,那么节流函数会按照一定的频率来执行函数
3.不管在这个中间有多少次触发这个事件,执行函数的频繁总是固定的

function throttled1(fn, delay = 500) {
    let oldtime = Date.now()
    return function (...args) {
        let newtime = Date.now()
        if (newtime - oldtime >= delay) {
            fn.apply(null, args)
            oldtime = Date.now()
        }
    }
}

45. 说说对React refs 的理解?应用场景?

创建ref的形式有三种:
1.传入字符串,使用时通过 this.refs.传入的字符串的格式获取对应的元素
2.传入对象,对象是通过 React.createRef() 方式创建出来,使用时获取到创建的对象中存在 current 属性就是对应的元素
3.传入hook,hook是通过 useRef() 方式创建,使用时通过生成hook对象的 current 属性就是对应的元素
在某些情况下,我们会通过使用refs来更新组件,但这种方式并不推荐,更多情况我们是通过props与state的方式进行去重新渲染子元素
但下面的场景使用refs非常有用:
1.对Dom元素的焦点控制、内容选择、控制
2.对Dom元素的内容设置及媒体播放
3.对Dom元素的操作和对组件实例的操作
4.集成第三方 DOM 库

46.applyMiddleware的作用是什么?

1.中间件都需要通过applyMiddlewares进行注册,
2.将所有的中间件组成一个数组,依次执行然后作为第二个参数传入到createStore中
3.applyMiddlewares调用实例:返回store对象
我们用 applyMiddleware 是为了改造 dispatch 的,所以 applyMiddleware 执行完后,dispatch 是变化了的,而 middlewareAPI 是 applyMiddleware 执行中分发到各个 middleware,所以必须用匿名函数包裹 dispatch, 这样只要 dispatch 更新了, middlewareAPI 中的 dispatch 应用也会发生变化

47.如何解决react页面不刷新?

\1. 深拷贝或者改变引用类型数据的地址
\2. Key最好不用index
\3. 在this.setState中使用一个回调来获取一个新的值
\4. 不要直接修改store中的值
\5. 在render中判断state.value值不等于空,再加载子组件

48 . 说说React中setState执行机制?

     一个组件的显示形态可以由数据状态和外部参数所决定,而数据状态就是state当需要修改里面的值的状态需要通过调用setState来改变,从而达到更新组件内部数据的作用 setState第一个参数可以是一个对象,或者是一个函数,而第二个参数是一个回调函数,用于可以实时的获取到更新之后的数据 在使用setState更新数据的时候,setState的更新类型分成: 同步和异步,在组件生命周期或React合成事件中,setState是异步在setTimeout或者原生dom事件中,setState是同步

49.说说你对受控组件和非受控组件的理解?应用场景?

     受控组件,简单来讲,就是受我们控制的组件,组件的状态全程响应外部数据 非受控组件,简单来讲,就是不受我们控制的组件一般情况是在初始化的时候接受外部数据,然后自己在内部存储其自身状态大部分时候推荐使用受控组件来实现表单,因为在受控组件中,表单数据由React组件负责处理如果选择非受控组件的话,控制能力较弱,表单数据就由DOM本身处理,但更加方便快捷,代码量少

50.说说React jsx转换成真实DOM的过程?

react中的jsx语法会通过babel转化为 js代码,以React.createElement函数形式存在,createElement函数返回一个ReactElement函数,ReactElement函数返回一个的虚拟节点,虚拟节点中嵌套虚拟节点,就形成了虚拟DOM,最后通过ReactDOM.render方法转化为真实DOM。babel在转化jsx过程中,会判断首字母的大小写当首字母为小写的时候,会被认为是原生DOM标签, 那么createElement中的第一个参数就是一个字符串,表示标签的名称当首字母为大写的时候,会被认为是组件,那么createElement中的第一个参数就是组件的名称,

51.说说你对@reduxjs/toolkit的理解?和react-redux有什么区别?

react-redux 是的官方 React UI 绑定层,允许您的 React 组件从 Redux 存储中读取数据,并将操作分派到存储以更新状态。
@reduxjs/toolkit 是对 Redux 的二次封装,开箱即用可的一个高效的 Redux 开发工具集,使得创建store、更新store更加方便

52.说说webpack中常见的loader?解决了什么问题?

Image-loader 加载并且压缩图片文件
Babel-loader 将es6转换为es5
Css-loader 加载css 支持模块化 压缩 文件导入
Style-loader 把css代码注入到js中 通过dom操作去加载css
css-loader:分析css 模块之间的关系,并合成⼀个css style-loader:把css-loader生成的内容,用style标签挂载到页面的head中 less-loader:开发中,我们也常常会使用less、sass、stylus预处理器编写css样式,使开发效率提高,这里需要使用less-loader raw-loader:在webpack中通过import方式导入文件内容,该loader并不是内置的,所以首先要安装,然后在 webpack.config.js 中进行配置 file-loader:把识别出的资源模块,移动到指定的输出⽬目录,并且返回这个资源在输出目录的地址(字符串) url-loader:可以处理理file-loader中的所有事情,但是遇到图片格式的模块,可以选择性的把图片转成base64格式的字符串,并打包到js中,对小体积的图片比较合适,大图片不合适

53.知道react里面的createPortal么,说说其使用场景?

Portal 将提供一种将子节点渲染到 DOM 节点中的方式,该节点存在于 DOM 组件的层次结构之外。
因此 Portals 适合脱离文档流(out of flow) 的组件,特别是 position: absolute 与 position: fixed的组件。比如模态框,通知,警告,goTop 等

54.![] == ![],![] == [],结果是什么?为什么?

①、根据运算符优先级 ,! 的优先级是大于 == 的,所以先会执行 ![]
②、根据上面提到的规则(如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false转换为0,而true转换为1),则需要把 false 转成 0
③、根据上面提到的规则(如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型值按照前面的规则进行比较,如果对象没有valueOf()方法,则调用 toString())
④、根据上面提到的规则(如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值)

55.什么是闭包,应用场景是什么?

闭包就是能够读取其他函数内部变量的函数,说白了闭包就是个函数,只不过是处于其他函数内部而已。
1.访问函数内部的变量
2.防止函数内部的变量执行完城后,被销毁,使其一直保存在内存中。

56.谈谈你是如何做移动端适配的?

[flex弹性布局]
[百分比]
[用框架搭建页面]
[viewport适配]
[媒体查询media]
[rem+viewport缩放(也成为1px适配)]

57.移动端1像素的解决方案?

  1. 移动端1像素的解决方案?
  2. 伪类+transform
  3. viewport + rem
  4. border-image
  5. background-image
  6. postcss-write-svg
    总结
    0.5px,相信浏览器肯定是会慢慢支持的,目前而言,如果能用的话,可以hack一下。
    对于老项目,建议采用transform+伪类。
    新项目可以设置viewport的scale值,这个方法兼容性好。
    postcss-write-svg简单易用,仅适合直线,圆角建议用transform+伪类实现

58.弹性盒中的缩放机制是怎样的

弹性盒中的项目设置flex-grow属性定义项目的放大比例,默认值为0,值越大,放大越厉害,且不支持负值; 而flex-shrink属性定义项目的缩小比例,默认值为1,数值越大,缩小越厉害,同样不支持负值;

59.说说你对TypeScript中泛型的理解及其应用场景?

泛型的本质是参数化类型,通俗的将就是所操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法的创建中,分别成为泛型类,泛型接口、泛型方法。
TypeScript 中不建议使用 any 类型,不能保证类型安全,调试时缺乏完整的信息。
TypeScript可以使用泛型来创建可重用的组件。支持当前数据类型,同时也能支持未来的数据类型。扩展灵活。可以在编译时发现你的类型错误,从而保证了类型安全。
使用泛型可以创建泛型函数、泛型接口,泛型类

60.说说你对TypeScript装饰器的理解及其应用场景

装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上,是一种在不改变原类和使用继承的情况下,动态地扩展对象功能同样的,本质也不是什么高大上的结构,就是一个普通的函数,@expression 的形式其实是Object.defineProperty的语法糖,expression 求值后必须也是一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入
场景 1.逻辑层消除繁琐的try/catch块,装饰器内统一输出函数日志 2.校验参数或返回值类型

61什么是React

React,用于构建用户界面的 JavaScript 库,只提供了 UI 层面的解决方案
遵循组件设计模式、声明式编程范式和函数式编程概念,以使前端应用程序更高效
使用虚拟 DOM 来有效地操作 DOM,遵循从高阶组件到低阶组件的单向数据流
帮助我们将界面成了各个独立的小块,每一个块就是组件,这些组件之间可以组合、嵌套,构成整体页面
react 类组件使用一个名为 render() 的方法或者函数组件return,接收输入的数据并返回需要展示的内容

React 特性有很多,如:
JSX 语法
单向数据绑定
虚拟 DOM
声明式编程
Component
React 存在的优势:
高效灵活
声明式的设计,简单使用
组件式开发,提高代码复用率
单向响应的数据流会比双向绑定的更安全,速度更快

62. 说说 Real DOM 和 Virtual DOM 的区别?优缺点?

两者的区别如下:
虚拟 DOM 不会进行排版与重绘操作,而真实 DOM 会频繁重排与重绘
虚拟 DOM 的总损耗是“虚拟 DOM 增删改+真实 DOM 差异增删改+排版与重绘”,真实 DOM 的总损耗是“真实 DOM 完全增删改+排版与重绘”

真实 DOM 的优势:
易用
缺点:
效率低,解析速度慢,内存占用量过高
性能差:频繁操作真实 DOM,易于导致重绘与回流
使用虚拟 DOM 的优势如下:
简单方便:如果使用手动操作真实 DOM 来完成页面,繁琐又容易出错,在大规模应用下维护起来也很困难
性能方面:使用 Virtual DOM,能够有效避免真实 DOM 数频繁更新,减少多次引起重绘与回流,提高性能
跨平台:React 借助虚拟 DOM,带来了跨平台的能力,一套代码多端运行
缺点:
在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化
首次渲染大量 DOM 时,由于多了一层虚拟 DOM 的计算,速度比正常稍慢

63. 什么是JSX

jsx是JavaScript的一种语法扩展,它跟模板语言很接近,但是它充分具备JavaScript的能力

JSX就是用来声明React当中的元素,React使用JSX来描述用户界面

JSX语法糖允许前端开发者使用我们最熟悉的类HTML标签语法来创建虚拟DOM在降低学习成本

64. React创建元素的方法?

React.createElement()
参考答案:
https://vue3js.cn/interview/React/Building%20components.html

65. class组件和函数组件区别

class组件是有状态的组件,可以定义state状态,函数组件无状态
class组件有生命周期的,函数组件无生命周期
class组件是由this对象,函数组件没有this对象
组件调用: class组件实例化后调用render方法调用,函数组件直接调用的。
class组件内部的话,render方法return返回渲染jsx模板,函数组件直接返回即可
ref获取子组件的对象,class组件可以直接获取到的,函数组件无法直接获取到。
绑定bind改变this指向,只适用于class组件

66. React 事件绑定的方式

React 事件绑定属性的命名采用驼峰式写法, 采用 JSX 的语法传入一个函数作为事件处理函数

事件绑定函数的方式

  1. 直接写函数名字{callback},

  2. 可以使用bind方法绑定调用 {callback.bind(this)}

67. 事件处理方法this指向改变

当我们把事件函数写成普通函数的形式时 , 调用函数使用state变量会报错,提示state变量不存在,

是因为

事件处理程序的函数式函数调用模式,在严格模式下,this指向undefined

render函数是被组件实例调用的,因此render函数中的this指向当前组件

解决方法: 1. 把普通函数改成箭头函数 2. 调用函数的时候使用bind方法改变this指向

68. React事件处理方法传值

调用的时候定义一个箭头函数 函数中调用方法传递参数据

<button onClick={()=> this.del(index) }>
点击

第二种方法 bind方法传递参数

<button onClick={this.del.bind(this,index) }>
点击

69 React如何获取表单数据

给文本框绑定value属性,value属性绑定state中定义的变量
给表单绑定onChange事件,调用定义的方法
在方法中我们获取e.target.value属性,赋给value属性绑定的变量

70. React条件渲染方法有哪些

if-else的条件渲染方法
三元运算符进行条件渲染,可以缩短代码量
switch的多条件渲染效果
HOC条件渲染

71. React怎么实现列表渲染

react中可以使用map方法渲染列表,return对应的页面结构即可, React 在渲染列表时,会要求开发者为每一个列表元素指定唯一的 key ,我们尽量不要使用index索引值作为key,如果对数据进行:逆序添加、逆序删除等破坏顺序操作:可能会引起页面更新错误问题。

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

key是虚拟DOM对象的唯一标识,在更新显示时key起到极其重要的作用 ,简单的来说就是为了提高diff的同级比较的效率,避免原地复用带来的副作用

react采用的是自顶而下的更新策略,每次小的改动都会生成一个全新的的vdom,从而进行diff,如果不写key,就会发生本来应该更新却没有更新
参考答案: https://vue3js.cn/interview/React/key.html

73. React组件样式的定义方式

外联样式

定义css文件,在组件中通过import导入css样式,

import “App.css”

内联样式

React推崇的是内联的方式定义样式。这样做的目的就在于让你的组件更加的容易复用

定义一个style属性,属性中定义对应的css样式即可,比如style={{fontSize:‘15px’}}

外层花括号是语法,内层花括号是对象边界符

74. Props校验数据类型

array(数组)、bool(布尔值)、func(函数number(数字)、object(对象)、string(字符串)

75.受控组件和非受控组件

受控组件
由React控制的输入表单元素而改变其值的方式,称为受控组件。
比如,给表单元素input绑定一个onChange事件,当input状态发生变化时就会触发onChange事件,从而更新组件的state。
非受控组件
非受控组件指的是,表单数据由DOM本身处理。即不受setState()的控制,与传统的HTML表单输入相似,input输入值即显示最新值。
在非受控组件中,可以使用一个ref来从DOM获得表单值。

76. props和state的区别

props是指组件间传递的一种方式,props自然也可以传递state。由于React的数据流是自上而下的,所以是从父组件向子组件进行传递;另外组件内部的this.props属性是只读的不可修改!

state是组件内部的状态(数据),不能够直接修改,必须要通过setState来改变值的状态,从而达到更新组件内部数据的作用。

77.react-roter-dom中V5和V6区别?

参考链接: https://www.bilibili.com/read/cv15666960

V5中Switch换成Routes标签,
V5中exact属性没有了,V6默认是精准匹配
V5中的component属性,V6用的element,element属性是组件标签
V6中重定向导航组件换成Navigate
V6中路由嵌套直接采用组件包裹的方式,可以不适用path绝对路径,
V6中的 相当于vue中router-view
获取参数和Hooks方法的变化
props获取V6中props值没有参数数据,必须采用Hooks的路由获取数据。
withRouter在V6版本中也被去掉了。

78.context状态树是怎么运行的?

在父组件中我们通过createContext() 创建一个空对象,在父组件的最外层我们使用Provider包裹数据,通过value绑定要传递的对象数据。
在嵌套的子组件中,我们有两种方式获取数据:
(1) 我们可以使用Customer标签,在标签中绑定一个箭头函数,函数的形参context就是value传递的数据
(2). class组件中我们可以定义static contextType=context对象,组件中直接使用this.context获取数据。

79.React生命周期分为几个阶段?

Mounting(挂载阶段):已插入真实 DOM
Updating(更新阶段):正在被重新渲染
Unmounting(卸载阶段):已移出真实 DOM

80. React旧生命周期有哪些问题?

(1) componentWillMount ,在ssr中 这个方法将会被多次调用, 所以会重复触发多遍,同时在这里如果绑定事件,
将无法解绑,导致内存泄漏 , 变得不够安全高效逐步废弃。
(2) componentWillReceiveProps 外部组件多次频繁更新传入多次不同的 props,会导致不必要的异步请求
(3) componetWillupdate, 更新前记录 DOM 状态, 可能会做一些处理,与componentDidUpdate相隔时间如果过长, 会导致 状态不太信

81. React新生命周期有哪些改变?

用 getDerivedStateFromProps替换了 compoentWillMount和compontWillReceiveProps生命周期函数
用getSnapshotBeforeUpdate函数替换componetWillUpdate方法,避免和CompoentDidUpdate函数中获取数据不一致的问题

82. react路由常用的组件有哪些?

HashRouter或BrowserRouter配置路由模式
Route 定义路由组件映射关系
Redirect 设置路由重定向
NavLink 或者Link 页面路由跳转
Switch 路由匹配,当path匹配到一个component之后,将不会再想下继续匹配,提高了程序效率

83. react路由传参的方式有哪些?

//隐士参数传递
(1) this.props.history.push({ pathname : ‘/user’ ,query : {id:100}})
this.props.location.query.id 获取query传递的参数据,刷新数据不在
(2) this.props.history.push({ pathname:‘/user’,state:{id: 1000 } }) this.props.location.state.id 获取state的数据,刷新数据还在
3. url传参方式 () history.location.search获取数据比较麻烦,得自己解析
4. 动态路由定义 /detail/:id => /detail/100 => location.match.params中接受的参数是 {id:100}

84. react路由跳转的方式有哪些?

声明式导航:
使用NavLink或者Link跳转, to属性后面跟字符串或者跟对象
编程式导航跳转:
props.history.push(url) 跳转页面可以返回上一页,保留历史记录
props.history.replace(url) 跳转页面,清空历史记录
props.history.go(num) 返回第几个页面
31. withRouter是干什么的?
不是所有组件都直接与路由相连(比如拆分的子组件)的,当这些组件需要路由参数时,使用withRouter就可以给此组件传入路由参数,将react-router的history、location、match三个对象传入props对象上,此时就可以使用this.props.history跳转页面了或者接受参数了

85. 什么是Redux?

在react中每个组件的state是由自身进行管理,包括组件定义自身的state、组件之间的通信通过props传递、使用Context实现数据共享等,如果让每个组件都存储自身相关的状态,理论上来讲不会影响应用的运行,但在开发及后期我们将比较难以维护,所以我们可以把数据进行集中式的管理,redux就是一个实现上述集中管理的容器的工具,redux并不是只应用在react中,还与其他界面库一起使用,如Vue

86. Redux的三大原则

state数据必须是单一数据源
redux中的state数据必须 是只读的,只能通过dispatch调用actions修改
Reducer必须使用纯函数来执行修改

87. redux的执行原理

React的组件需要获取或者修改页面的数据,通过dispatch方法调用actions进入到Reducer函数中修改state的数据内容,state更新后,通知组件更新页面即可。

88. redux的使用步骤

创建一个store文件夹,新建一个index.js文件
文件中导入redux的createStore方法,用于创建公共数据区域
创建一个reducer纯函数,接受两个参数state,actions分别表示分别表示数据和操作state的方法,返回state数据给组件页面
把reducer作为createStore的参数抛出
在需要使用的页面导入store文件,通过store.getState获取数据,通过store.dispatch触发action修改state数据
store.subscrible 方法监听 store 的改变,避免数据不更新

89. super() 和super(props)有什么区别?

在 React 中,类组件基于 ES6,所以在 constructor 中必须使用 super
在调用 super 过程,无论是否传入 props,React 内部都会将 porps 赋值给组件实例 porps 属性中
如果只调用了 super(),那么 this.props 在 super() 和构造函数结束之间仍是 undefined

90. React的事件机制总结

React事件机制总结如下:

  • React 上注册的事件最终会绑定在document这个 DOM 上,而不是 React 组件对应的 DOM(减少内存开销就是因为所有的事件都绑定在 document 上,其他节点没有绑定事件)
  • React 自身实现了一套事件冒泡机制,所以这也就是为什么我们 event.stopPropagation()无效的原因。
  • React 通过队列的形式,从触发的组件向父组件回溯,然后调用他们 JSX 中定义的 callback
  • React 有一套自己的合成事件 SyntheticEvent

91. 说说对React refs 的理解?应用场景?

创建ref的形式有三种:

  • 传入字符串,使用时通过 this.refs.传入的字符串的格式获取对应的元素
  • 传入对象,对象是通过 React.createRef() 方式创建出来,使用时获取到创建的对象中存在 current 属性就是对应的元素
  • 传入hook,hook是通过 useRef() 方式创建,使用时通过生成hook对象的 current 属性就是对应的元素

在某些情况下,我们会通过使用refs来更新组件,但这种方式并不推荐,更多情况我们是通过props与state的方式进行去重新渲染子元素

但下面的场景使用refs非常有用:

  • 对Dom元素的焦点控制、内容选择、控制
  • 对Dom元素的内容设置及媒体播放
  • 对Dom元素的操作和对组件实例的操作
  • 集成第三方 DOM 库

92. 说说对高阶组件的理解?应用场景?

一个函数的参数是一个函数,或者 函数的返回值是一个函数,我们称这类函数是高阶函数。
什么是React高阶组件:一个组件的参数是组件,并且返回值是一个组件,我们称这类组件为高阶组件
withRouter() memo() react-redux中connect方法是高阶组件
React 中的高阶组件主要有两种形式:属性代理 和 反向继承。
属性代理: 是 一个函数接受一个 WrappedComponent 组件作为参数传入,并返回一个继承了 React.Component 组件的类,且在该类的 render() 方法中返回被传入的 WrappedComponent 组件

反向继承:是 一个函数接受一个 WrappedComponent 组件作为参数传入,并返回一个继承了该传入 WrappedComponent 组件的类,且在该类的 render() 方法中返回 super.render() 方法。

93. 说说对Redux中间件的理解?常用的中间件有哪些?

Redux中,中间件就是放在就是在dispatch过程,在分发action进行拦截处理
前面我们了解到了Redux整个工作流程,当action发出之后,reducer立即算出state,整个过程是一个同步的操作
那么如果需要支持异步操作,或者支持错误处理、日志监控,这个过程就可以用上中间件,其本质上一个函数,对store.dispatch方法进行了改造,在发出 Action和执行 Reducer这两步之间,添加了其他功能

常用的redux中间件,如:
redux-thunk:用于异步操作
redux-logger:用于日志记录

中间件都需要通过applyMiddlewares进行注册,作用是将所有的中间件组成一个数组,依次执行然后作为第二个参数传入到createStore中

const store = createStore(
reducer,
applyMiddleware(thunk, logger)
);

94. React中常见的Hooks方法有哪些?

useState

useState()用于为函数组件引入状态。在useState()中,数组第一项为一个变量,指向状态的当前值。类似this.state,第二项是一个函数,用来更新状态,类似setState

useEffect

useEffect()接受两个参数,第一个参数是你要进行的异步操作,第二个参数是一个数组,用来给出Effect的依赖项。只要这个数组发生变化,useEffect()就会执行

useRef

相当于class组件中的createRef的作用,ref.current获取绑定的对象

useContext

接受context状态树传递的数据内容

useReducer

接受reducer函数和状态的初始值作为参数,返回一个数组,其中第一项为当前的状态值,第二项为发送action的dispatch函数

userMemo useCallback

useMemo 和 useCallback接收的参数都是一样,第一个参数为回调,第二个参数为要依赖的数据
共同作用:仅仅依赖数据发生变化, 才会调用,也就是起到缓存的作用。useCallback缓存函数,useMemo 缓存返回值。

95. useMemo, useCallback做了那些性能优化

useMemo 主要缓存复杂运算的数据的结果,第二个参数,定义监听的变量,需要返回一个结果。

当父组件的组件更新的时候会导致子组件的重新渲染,但是如果父组件的更新的数据没有传递给子组件的话,这个时候如果还让子组件重新渲染的化,就会导致组件的更新的性能消耗比较大。

所以说这个时候我们可以使用useMemo, 或者React中内置的memo方法对子组件进行缓存,这样的话只有父组件更新跟子组件相关联的数据的时候才会导致子组件的重新渲染,从而提高组件的渲染性能。

但是如果我们给子组件传递方法的时候,上面memo方法的缓存就不起作用了,原因是父组件没更新一次会导致方法的重新调用,进而导致子组件的重新更新,所以这个时候我们可以使用useCallback对传递的方法进行缓存,监听数据更新后才会重新调用方法,从而提高组件的渲染性能。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值