react前端面试题

1.SPA(单页应用)首屏加载速度慢怎么解决?

   首屏时间(First Contentful Paint),指的是浏览器从响应用户输入网址地址,到首屏内容渲染完成的时间,此时整个网页不一定要全部渲染完成,但需要展示当前视窗需要的内容;首屏加载可以说是用户体验中最重要的环节

       1,减少入口文件体积:常用的手段是路由懒加载,只有在解析路由时才会加载组件;
       2,静态资源本地缓存: 后端返回资源: 采用HTTP缓存;前端合理利用:localStorage;
       3,UI框架按需加载 
      4,避免组件重复打包
      5,图片资源压缩
     6,开启GZip压缩,拆完包后,我们再用gzip做一下压缩,安装compression-webpack-plugin webpack中配置安装
2.Vue中自定义指令的理解,应用场景有哪些?
           注册一个自定义指令有全局注册与局部注册
全局注册注册主要是用过Vue.directive方法进行注册
         注册一个自定义指令有全局注册与局部注册,全局注册注册主要是用过Vue.directive方法进行注册,局部注册通过在组件options选项中设置directive属性;
应用场景:1,输入框防抖,2,图片懒加载;3,一键copy功能
3.说说你对事件循环的理解?
  事件循环:在JavaScript中,所有的任务都可以分为:同步任务,异步任务;
    同步任务进入主线程,即主执行栈,异步任务进入任务队列,主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。上述过程的不断重复就是事件循环
4.说说javascript内存泄漏的几种情况?

内存泄漏(Memory leak)是在计算机科学中,由于疏忽或错误造成程序未能释放已经不再使用的内存

并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费

程序的运行需要内存。只要程序提出要求,操作系统或者运行时就必须供给内存

对于持续运行的服务进程,必须及时释放不再用到的内存。否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃

1,意外的全局变量,
2,闭包引起的内存泄漏
3,DOM之外的引用
4,被遗漏的定时器和回调函数


5.大文件如何做断点续传?
     整体思路比较简单,拿到文件,保存文件唯一性标识,切割文件,分段上传,每次上传一段,根据唯一性标识判断文件上传进度,直到文件的全部片段上传完毕

6.原生js如何实现上拉加载下拉刷新?
     上拉加载的本质是页面触底,或者快要触底时的动作: 判断页面触底我们需要先了解一下下面几个属性 scrollTop:滚动视窗的高度距离window顶部的距离,它会随着往上滚动而不断增加,初始值是0,它是一个变化的值 clientHeight:它是一个定值,表示屏幕可视区域的高度; scrollHeight:页面不能滚动时也是存在的,此时scrollHeight等于clientHeight。scrollHeight表示body所有元素的总长度(包括body元素自身的padding);.下拉刷新的本质是页面本身置于顶部时,用户下拉时需要触发的动作: 关于下拉刷新的原生实现,主要分成三步: (1)监听原生touchstart事件,记录其初始位置的值,e.touches[0].pageY; (2)监听原生touchmove事件,记录并计算当前滑动的位置值与初始位置值的差值,大于0表示向下拉动,并借助CSS3的translateY属性使元素跟随手势向下滑动对应的差值,同时也应设置一个允许滑动的最大值; (3)监听原生touchend事件,若此时元素滑动达到最大值,则触发callback,同时将translateY重设为0,元素回到初始位置

7.说说设备像素、css像素、设备独立像素、dpr、ppi之间的区别?
CSS像素(css pixel, px): 适用于web编程,在 CSS 中以 px 为后缀,是一个长度单位;
     设备像素(device pixels),又称为物理像素,指设备能控制显示的最小物理单位,不一定是一个小正方形区块,也没有标准的宽高,只是用于显示丰富色彩的一个“点”而已;
设备独立像素(Device Independent Pixel):与设备无关的逻辑像素,代表可以通过程序控制使用的虚拟像素,是一个总体概念,包括了CSS像素;
dpr(device pixel ratio),设备像素比,代表设备独立像素到设备像素的转换关系,在JavaScript中可以通过 window.devicePixelRatio 获取;
ppi (pixel per inch),每英寸像素,表示每英寸所包含的像素点数目,更确切的说法应该是像素密度。数值越高,说明屏幕能以更高密度显示图像;
无缩放情况下,1个CSS像素等于1个设备独立像素;设备像素由屏幕生产之后就不发生改变,而设备独立像素是一个虚拟单位会发生改变;PC端中,1个设备独立像素 = 1个设备像素 (在100%,未缩放的情况下);在移动端中,标准屏幕(160ppi)下 1个设备独立像素 = 1个设备像素;设备像素比(dpr) = 设备像素 / 设备独立像素;每英寸像素(ppi),值越大,图像越清晰;
8.谈谈你对BFC的理解?
BFC(Block Formatting Context)块格式化上下文, 是Web页面的可视CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。简单的理解:BFC就是一个块级容器,它会隔离外部,让盒子里面的元素不影响外面的元素,也就是在搭建页面的时候,不影响外面的布局。
 不使用BFC:内部元素使用浮动的时候,外面的盒子计算不到高度,就会导致高度坍塌
  如果两个块级盒子都设置了margin值,两个盒子相邻的那一边的margin就会重叠

 特性:属于同一个DFC的两个相邻容器的上下margin会重叠
          计算BFC高度时,浮动元素也会参与计算
          BFC的区域不会与浮动容器发生重叠
          BFC内的容器在垂直方向依次排列
          元素的margin-left与其包含块的border-left相接触
          BFC是独立容器,容器内部元素不会影响容器外部元素
 
 触发条件:最常见的是通过 overflow: hidden 来构建 BFC。一般情况下,它的副作用最小。但如果元素下有超出盒子范围的内容,会被截掉, 

 解决问题:解决边距重叠问题:我们只需要在其中一个块级元素外面包裹一层容器,使两个块级元素不属于同一层级,并且触发BFC
  解决高度塌陷问题:如果盒子里面的元素加了浮动,计算外面盒子的高度不会计算浮动的盒子高度,因为浮动不占空间。这个时候我们就需要在外面的盒子触发BFC,这样使他即使内部元素加了浮动也计算浮动元素的高度,不会导致高度坍塌
  解决相邻盒子浮动区域重叠问题:给相邻的盒子也加上浮动,给相邻的盒子设置overflow:hidden
9.说说TCP为什么需要三次握手和四次握手?
三次握手:原因一:避免历史连接;原因二:同步双方初始序列号;原因三:避免资源浪费;
四次挥手:1.防止具有相同「四元组」的「旧」数据包被收到;
2,保证「被动关闭连接」的一方能被正确的关闭,即保证最后的 ACK 能让被动关闭使用CDN方接收,从而帮助其正常关闭;
10.前端性能优化的手段有哪些?
1,减少http请求数;2. 图片优化;3. 使用CDN;4. 开启GZIP;5. 样式表和JS文件的优化;6. 使用无cookie域名;7. 前端代码结构的优化

11.什么是虚拟DOM?
虚拟DOM是真实DOM在内存中的表示,ul的表示形式保存在内存中,并且与实际的DOM同步,这是一个发生在渲染函数被调用和元素在屏幕上显示的步骤,整个过程被称为调和

12.类组件和函数组件之间的区别是什么?
类组件可以使用其他特性,如状态和生命周期钩子,并且他有this

函数组件只能接收props渲染到页面,无状态组件,没有this,不能使用生命周期钩子

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

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

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

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

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

15.在react中如何处理事件? 
为了解决跨浏览器的兼容性问题,SyntheticEvent 实例将被传递给你的事件处理函数,SyntheticEvent是 React 跨浏览器的浏览器原生事件包装器,它还拥有和浏览器原生事件相同的接口,包括 stopPropagation() 和 preventDefault()。

比较有趣的是,React 实际上并不将事件附加到子节点本身。React 使用单个事件侦听器侦听顶层的所有事件。这对性能有好处,也意味着 React 在更新 DOM 时不需要跟踪事件监听器。


16.class组件和函数组件区别
class组件是有状态的组件,可以定义state状态,函数组件无状态
class组件有生命周期的,函数组件无生命周期
class组件是由this对象,函数组件没有this对象
组件调用: class组件实例化后调用render方法调用,函数组件直接调用的。
class组件内部的话,render方法return返回渲染jsx模板,函数组件直接返回即可
ref获取子组件的对象,class组件可以直接获取到的,函数组件无法直接获取到。
绑定bind改变this指向,只适用于class组件
17.state和props区别是什么?
相同点:都是普通的js对象,他们包含着影响渲染输出的信息

不同点:state是组件自己管理数据,控制自己的状态,可变

props是外部传入的数据参数,不可变

没有state的叫做无状态组件,有state的叫有状态组件

多用props,少用state

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

事件绑定函数的方式

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

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

19. 事件处理方法this指向改变
当我们把事件函数写成普通函数的形式时 , 调用函数使用state变量会报错,提示state变量不存在,

是因为

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

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

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

20.React事件处理方法传值
1.调用的时候定义一个箭头函数 函数中调用方法传递参数据

<button onClick={()=> this.del(index) }>
   点击
</button>
2.  bind方法传递参数

<button onClick={this.del.bind(this,index) }>
  点击
</button>
21. React如何获取表单数据?
给文本框绑定value属性,value属性绑定state中定义的变量
给表单绑定onChange事件,调用定义的方法
在方法中我们获取e.target.value属性,赋给value属性绑定的变量
22.为什么不直接更新state?
如果试图直接更新state,就不会重新渲染组件

需要使用setState()方法更新state,它对state对象进行更新,当state改变时,组件通过重新渲染来响应

23.React条件渲染方法有哪些?
if-else的条件渲染方法
三元运算符进行条件渲染,可以缩短代码量
switch的多条件渲染效果
HOC条件渲染
24.React怎么实现列表渲染?
react中可以使用map方法渲染列表,return对应的页面结构即可, React 在渲染列表时,会要求开发者为每一个列表元素指定唯一的 key ,我们尽量不要使用index索引值作为key,如果对数据进行:逆序添加、逆序删除等破坏顺序操作:可能会引起页面更新错误问题。

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

react采用的是自顶而下的更新策略,每次小的改动都会生成一个全新的的vdom,从而进行diff,如果不写key,就会发生本来应该更新却没有更新 

26. React组件样式的定义方式?
外联样式

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

import "App.css"

内联样式

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

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

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

27.Props校验数据类型
array(数组)、bool(布尔值)、func(函数number(数字)、object(对象)、string(字符串)

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

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

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

30.react-roter-dom中V5和V6区别?
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版本中也被去掉了。
31.父传子通信流程
在父组件中的子组件标签上绑定自定义属性,挂载传递的数据
子组件中props接受传递的数据,直接使用即可
32.子传父通信的流程
父组件中子组件标签上绑定一个属性,传递一个方法给子组件
子组件中通过props接受这个方法,直接调用,传递相应的参数即可
33.非父子组件通信
状态提升(中间人模式) 
React中的状态提升概括来说,就是将多个组件需要共享的状态提升到它们最近的父组件,在父组件上改变这个状态然后通过props分发给子组件
context状态树传参
34.context状态树是怎么运行的?
在父组件中我们通过createContext() 创建一个空对象,在父组件的最外层我们使用Provider包裹数据,通过value绑定要传递的对象数据。
在嵌套的子组件中,我们有两种方式获取数据: 
(1) 我们可以使用Customer标签,在标签中绑定一个箭头函数,函数的形参context就是value传递的数据 
(2). class组件中我们可以定义static contextType=context对象,组件中直接使用this.context获取数据。
35.React生命周期分为几个阶段?
Mounting(挂载阶段):已插入真实 DOM 
Updating(更新阶段):正在被重新渲染 
Unmounting(卸载阶段):已移出真实 DOM

36.简述React的生命周期函数?
挂载阶段: 
- constructor() 在 React 组件挂载之前,会调用它的构造函数。 
- componentWillMount: 在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。 
- componentDidMount(): 在组件挂载后(插入 DOM 树中)立即调用

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

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

38. React新生命周期有哪些改变?
用 getDerivedStateFromProps替换了 compoentWillMount和compontWillReceiveProps生命周期函数
用getSnapshotBeforeUpdate函数替换componetWillUpdate方法,避免和CompoentDidUpdate函数中获取数据不一致的问题
39. react的路由几种模式,是什么?
两种路由模式: 
一种是Hash路由模式,用的是HashRouter组件 
一种是历史路由模式,用的是BrowserRouter组件绑定

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

41.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}
42.react路由跳转的方式有哪些?
声明式导航: 
使用NavLink或者Link跳转, to属性后面跟字符串或者跟对象 
编程式导航跳转: 
props.history.push(url) 跳转页面可以返回上一页,保留历史记录 
props.history.replace(url) 跳转页面,清空历史记录 
props.history.go(num) 返回第几个页面

43 .react路由嵌套如何配置? 
配置父组件的路由地址,在父组件中配置子组件的路由映射关系
关闭父组件路由配置exact属性,避免精准匹配
父组件路由地址作为子组件路由地址的开始的一部分。比如父组件是/index 子组件应该是/index/子组件地址
44. withRouter是干什么的?
是所有组件都直接与路由相连(比如拆分的子组件)的,当这些组件需要路由参数时,使用withRouter就可以给此组件传入路由参数,将react-router的history、location、match三个对象传入props对象上,此时就可以使用this.props.history跳转页面了或者接受参数了

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

46.Redux的三大原则 
state数据必须是单一数据源
redux中的state数据必须 是只读的,只能通过dispatch调用actions修改
Reducer必须使用纯函数来执行修改
47.redux的执行原理
React的组件需要获取或者修改页面的数据,通过dispatch方法调用actions进入到Reducer函数中修改state的数据内容,state更新后,通知组件更新页面即可。

48.redux的使用步骤
创建一个store文件夹,新建一个index.js文件
文件中导入redux的createStore方法,用于创建公共数据区域
创建一个reducer纯函数,接受两个参数state,actions分别表示分别表示数据和操作state的方法,返回state数据给组件页面
把reducer作为createStore的参数抛出
在需要使用的页面导入store文件,通过store.getState获取数据,通过store.dispatch触发action修改state数据
store.subscrible 方法监听 store 的改变,避免数据不更新
49.React Router与常规路由有何不同? 
主题    常规路由    React 路由
参与的页面    每个视图对应一个新文件    只涉及单个HTML页面
URL 更改    HTTP 请求被发送到服务器并且接收相应的 HTML 页面    仅更改历史记录属性
体验    用户实际在每个视图的不同页面切换    用户认为自己正在不同的页面间切换
50.state和props有什么区别 
相同点: 
两者都是 JavaScript 对象 
两者都是用于保存信息 
props 和 state 都能触发渲染更新 
区别: 
props 是外部传递给组件的,而 state 是在组件内被组件自己管理的,一般在 constructor 中初始化 
props 在组件内部是不可修改的,但 state 在组件内部可以进行修改 
state 是多变的、可以修改

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

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

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

54.说说对React refs 的理解?应用场景?
创建ref的形式有三种: 
- 传入字符串,使用时通过 this.refs.传入的字符串的格式获取对应的元素 
- 传入对象,对象是通过 React.createRef() 方式创建出来,使用时获取到创建的对象中存在 current 属性就是对应的元素 
- 传入hook,hook是通过 useRef() 方式创建,使用时通过生成hook对象的 current 属性就是对应的元素

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

但下面的场景使用refs非常有用: 
- 对Dom元素的焦点控制、内容选择、控制 
- 对Dom元素的内容设置及媒体播放 
- 对Dom元素的操作和对组件实例的操作 
- 集成第三方 DOM 库

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

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

56.说说对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)
);
57.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 缓存返回值。

58.useMemo, useCallback做了那些性能优化?
useMemo 主要缓存复杂运算的数据的结果,第二个参数,定义监听的变量,需要返回一个结果。

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

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

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

 59.react中ref的使用方式?
1.可以直接写一个字符串,不过它只适用于类组件

2.createRef和useRef来定义ref变量,ref.current获取数据

3.可以使用箭头函数的方式,提前定义一个变量,箭头函数的形参就是当前对象 

const App = ()=>{
  let h = useRef();
 
  let inp = null;//定义一个空变量
 
  const setVal = ()=>{
    console.log(inp.value);
  }
  return (
    <div>
      <h3 ref={h}>ceshi</h3>
      <button onClick={()=>console.log(h.current)}>获取</button>
 
      <hr />
      <input placeholder="输入内容" ref={(el)=>{ inp = el; }} onChange={setVal}/>
    </div>
  )
}

ref属性不能直接绑定到函数子组件的,函数组件没有this对象,无法获取函数子组件的对象内容,最后函数组件forwardRef高阶组件组件,可以把ref属性通过参数的参数传递到函数子组件的内部,对ref属性进行转发的操作

60.你对“单一事实来源”有什么理解? 
 Redux 使用 “Store” 将程序的整个状态存储在同一个地方。因此所有组件的状态都存储在 Store 中,并且它们从 Store 本身接收更新。单一状态树可以更容易地跟踪随时间的变化,并调试或检查程序

61.SPA(单页应用)首屏加载速度慢怎么解决?
 1,减少入口文件体积:常用的手段是路由懒加载,只有在解析路由时才会加载组件;
 2,静态资源本地缓存: 后端返回资源: 采用HTTP缓存;前端合理利用:localStorage;
 3,UI框架按需加载 
 4,避免组件重复打包
 5,图片资源压缩
 6,开启GZip压缩,拆完包后,我们再用gzip做一下压缩,安装compression-webpack-plugin
webpack中配置安装

62.BFC的理解
BFC(Block Formatting Context)块格式化上下文,简单的理解:BFC就是一个块级容器,它会隔离外部,让盒子里面的元素不影响外面的元素,也就是在搭建页面的时候,不影响外面的布局。

不使用BFC:内部元素使用浮动的时候,外面的盒子计算不到高度,就会导致高度坍塌
        如果两个块级盒子都设置了margin值,两个盒子相邻的那一边的margin就会重叠

触发条件:最常见的是通过 overflow: hidden 来构建 BFC。一般情况下,它的副作用最小。但如果元素下有超出盒子范围的内容,会被截掉,

解决问题:

        1.解决边距重叠问题:我们只需要在其中一个块级元素外面包裹一层容器,使两个块级元素不属于同一层级,并且触发BFC
        2.解决高度塌陷问题:如果盒子里面的元素加了浮动,计算外面盒子的高度不会计算浮动的盒子高度,因为浮动不占空间。这个时候我们就需要在外面的盒子触发BFC,这样使他即使内部元素加了浮动也计算浮动元素的高度,不会导致高度坍塌
        3.解决相邻盒子浮动区域重叠问题:给相邻的盒子也加上浮动,给相邻的盒子设置overflow:hidden

63.说说javascript内存泄漏的几种情况?
1.意外的全局变量

一个未声明变量的引用会在全局对象中创建一个新的变量。

2.闭包引起的内存泄漏

闭包可以使变量常驻内存,但如果使用不当就会在成内存泄漏

3.DOM之外的引用

4.被遗漏的定时器和回调函数

怎样避免内存泄漏

1)减少不必要的全局变量,或者生命周期较长的对象,及时对无用的数据进行垃圾回收;

2)注意程序逻辑,避免“死循环”之类的 ;

3)避免创建过多的对象  原则:不用了的东西要及时归还。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值