目录
3.说说Real DOM和Virtual DOM的区别?优缺点?
28. React中getDerivedStateFromProps使用方式?
32.现在有一个父组件A, 嵌套一个子组件B,请简述组件A,B组件生命周期的挂载阶段执行流程?
35. Redux 和 Vuex 有什么区别,它们有什么共同思想吗?
37.shouldComponentUpdate如何做子组件性能优化?
46.useMemo,memo, useCallback如何提升性能呢?
48.说说你对useEffect的理解,可以模拟哪些生命周期?
49.说说React中setState和replaceState的区别?
54.说说你对@reduxjs/toolkit的理解?和react-redux有什么区别?
55.知道react里面的createPortal么,说说其使用场景?
56.说说AMD、CMD、commonJS模块化规范的区别?
60.React的props.children使用map函数来遍历会收到异常显示,为什么?应该 如何遍历?
62.redux中同步action与异步action最大的区别是什么?
63.在使用redux过程中,如何防止定义的action-type的常量重复?
68.说说reduce方法的作用?自己手动封装一个reduce,写出其核心代码?
70.说说你对TypeScript中泛型的理解及其应用场景?
71.说一说设备像素、css像素、设备独立像素、dpr、ppi之间的区别?
72.说说webpack proxy的工作原理?为什么能够解决跨域?
1.什么是React?
React是构建用户界面的JavaScript库,只提供了UI层面的解决方案,遵循组件设计模式,声明式编程,函数式编程,使用虚拟DOM来有效的操作DOM,遵循高阶组件到低阶组件的单项数据流。
2.React特性?
JSX语法,
单项数据绑定
虚拟DOM
声明式编程
Component
存在的优势:
高效灵活,
声明式设计,简单使用,
组件式开发,提高代码的复用率。
单向相应的数据流比双向绑定的更加安全,速度更快。
3.说说Real DOM和Virtual DOM的区别?优缺点?
两者的区别:
虚拟DOM不会进行排版和重绘操作,而真实Dom会频繁的重排和重绘
虚拟DOM 的总消耗是 “虚拟DOM的增删改 + 真实DOM的差异增删改 + 排版和重绘,真实DOM的总消耗是 真实DOM的完全增删改 + 排版和重绘
优缺点:
真实DOM的优势: 易用
缺点:
效率低,解析速度慢,内存占用量过高
性能差: 频繁的操作真实DOM。易于导致重绘和回流
使用虚拟DOM的优势:
简单方便: 如果使用手动操作真实DOm 来完成页面,频繁又容易出错,在大规模应用下维护起来也比较困难
性能方面: 使用虚拟DOM 能够有效的避免真实DOM数据的频繁更新,建胡搜啊多次引起的重绘与回流,提高性能
跨平台: react 借助虚拟DOM,带来了跨平台的能力,一套代码多端运行
缺点: 首次渲染大量 DOM 时,由于多了一层虚拟 DOM 的计算,速度比正常稍慢
4.React 生命周期:
创建阶段:
constroctor 初始化
componentWillMount 页面渲染之前
componentDidMount 页面渲染完毕
更新阶段:
componentWillReceiveProps 接收组件改变后的props
shouldComoponentUpdate 控制组件重新渲染的生命周期
render
componentWillUpdate 更新渲染页面前
componentDIdUpdate 页面渲染之后
卸载阶段:
componentWillUnmount 组件卸载数据销毁 阶段
5. React旧生命周期有哪些问题?
(1) componentWillMount ,在ssr中 这个方法将会被多次调用, 所以会重复触发多遍,同时在这里如果绑定事件,
将无法解绑,导致内存泄漏 , 变得不够安全高效逐步废弃。
(2) componentWillReceiveProps 外部组件多次频繁更新传入多次不同的 props,会导致不必要的异步请求
(3) componetWillupdate, 更新前记录 DOM 状态, 可能会做一些处理,与componentDidUpdate相隔时间如果过长, 会导致 状态不太信
6.React新生命周期有哪些改变?
用 getDerivedStateFromProps替换了 compoentWillMount和compontWillReceiveProps生命周期函数
用getSnapshotBeforeUpdate函数替换componetWillUpdate方法,避免和CompoentDidUpdate函数中获取数据不一致的问题
7.React和Vue的区别?
React 的思路是 HTML in JavaScript 也可以说是 All in JavaScript,通过 JavaScript 来生成 HTML,所以设计了 JSX 语法,还有通过 JS 来操作 CSS。
而Vue 是把 HTML,CSS,JavaScript 组合到一起,用各自的处理方式,Vue 有单文件组件,可以把 HTML、CSS、JS 写到一个文件中,HTML 提供了模板引擎来处理。
8.JSX语法规范?
1.定义虚拟Dom不用写引号
例如:const vdom = <h1>Hello, React</h1> //不用引号
2.标签种混入js表达式要有{}
3.样式类名指定使用className
4.内联样式,要用style={{key:value}}的形式去写
5.必须只有一个根标签
6.标签需要闭合
7.标签首字母:
1)若小写字母开头,则将标签改为html中同名元素
2)若大写字母开头,react则去渲染对应的组件,若组件没有定义,则报错
9.渲染列表为什么要使用key?
React 会在状态发生变化时,对真实 DOM 树按需批量更新,产生新的 UI。
为此底层做的工作是:将新旧两棵虚拟 DOM 树进行 diff 对比,计算出 patch 补丁,打到真实 DOM 树上。
为了高效,React 的 diff 算法做了限制:
只做同层级的节点对比,不跨层级比较;
如果元素的类型不同(如从 p 变成 div),那它们就是不相同的,会销毁整个旧子树,并调用其下组件的卸载钩子,然后再创建全新的树,相当消耗性能。
如果类型相同,会进行打补丁操作(如更新 className 和标签下的文本内容)
但这样做会有一个问题,如果同级的多节点 只是位置发生了变化,但因为相同索引位置对不上,又发现不能复用,就要销毁一棵树并创建一棵新树,实在是太过于低效了。
于是 *React 给开发者提供 key 来标记节点,来优化 React diff 算法,告知 React 某个节点其实没有被移除或不能被原地复用,只是换了位置而已,让 React 更新一下位置*。
如果最终找到该属性的值,则返回结果。
10.函数组件和类组件的区别?
-
语法上的区别:
函数式组件是一个纯函数,它是需要接受props参数并且返回一个React元素就可以了。类组件是需要继承React.Component的,而且class组件需要创建render并且返回React元素,语法上来讲更复杂。
-
调用方式
函数式组件可以直接调用,返回一个新的React元素;类组件在调用时是需要创建一个实例的,然后通过调用实例里的render方法来返回一个React元素。
-
状态管理
函数式组件没有状态管理,类组件有状态管理。
-
使用场景
类组件没有具体的要求。函数式组件一般是用在大型项目中来分割大组件(函数式组件不用创建实例,所以更高效),一般情况下能用函数式组件就不用类组件,提升效率
11.React受控组件和非受控组件的区别?
受控组件
表单组件的状态/数据只由state 维护 修改只能通过setState()来更新,
表单数据是由 React 组件来管理
非受控组件
使用ref来从 DOM 节点中获取表单数据。
表单数据将交由 DOM 节点来处理
12.setState 是同步的还是异步的?
setState是同步还是异步,不是绝对的,根据不同情况,是不一样的,如下:
1、同步的情况
1)setState在setTimeout中是同步的。
2)setState在原生事件中是同步的,即通过dom绑定事件的方式实现。
2、异步的情况
1)setstate在合成事件中是异步的,这里说的异步实际上是react的批量更新,达到了提升性能的目的。
2)setstate在生命周期中是异步的
13.Props 和 state 的区别?
props
主要是用于组件之间传递参数,获取组件的属性值。 组件之间数据单向流动 ,从父组件流向子组件。
对于外界/父组件的属性值,无法直接修改,它是只读的。
state
主要用于组件更新控制,如果想重新渲染或更新组件,只需要修改state即可,然后根据具体修改的state,
重新渲染用户界面(无需操作DOM对象);
本组件内的数据 相对封闭的单元/结构的数据PR
14.Props 可以校验那些数据类型?
optionalArray: PropTypes.array, //数组
optionalBool: PropTypes.bool, //布尔
optionalFunc: PropTypes.func,//函数
optionalNumber: PropTypes.number,//数值
optionalObject: PropTypes.object, //对象
optionalString: PropTypes.string, //字符串
optionalSymbol: PropTypes.symbol,//symbol
15.React 父子传值及子父传值?
父子:
1.父组件提供要传递的state数据
2.给子组件标签添加属性,值为 state 中的数据
3.子组件中通过 props 接收父组件中传递的数据
子父:
-
父组件提供一个回调函数(用于接收数据)
-
将该函数作为属性的值,传递给子组件
-
子组件通过 props 调用回调函数
-
将子组件的数据作为参数传递给回调函数
16.React 兄弟组件传值方式?
将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态 l
思想:状态提升 l
公共父组件职责:
-
提供共享状态
-
提供操作共享状态的方法 l
-
要通讯的子组件只需通过 props 接收状态或操作状态的方法
17.说说Real diff算法是怎么运作的?
在某一时间节点调用react render() 方法,会创建一棵由react元素组成的树。在下一次state,props更新时,相同的render() 方法会返回一棵不同的树,react 需要基于这两棵树之间的差别来判断如何有效率的更新UI,以保证当前UI与最新的树保持同步。
18.说说Connect组件的原理是什么?
connect 的
第一个参数是 mapStateToProps 这个函数允许我们将 store 中的数据作为 props 绑定到组件上 connect 的
第二个参数是 mapDispatchToProps 由于更改数据必须要触发action, 因此在这里的主要功能是将 action 作为props 绑定到 组件上 Provider就是react-redux中的一个组件, Provider 做的事情也简单, 它就是一个容器组件, 会把嵌套的内容原封不动作为自己的子组件渲染出来. 它还会把外界传给它的 props.store 放到 context
19.React路由的两种模式?
Hash模式,该模式会在路径前加入“#”号成为一个哈希值;
History模式,该模式允许操作浏览器的曾经标签页或者框架里访问的会话历史记录。
20.React 语法糖的本质是什么?
Jsx语法糖的本质: 通过babel转成 react crateElement 函数,
然后这个函数执行完后,会返回一个vnode
通过vnode 的patch 或者是其他的一个方法,最后渲染页面。
21.为什么react元素有一个$$type属性?
目的是为了防止 XSS 攻击
。因为 Synbol
无法被序列化,所以 React
可以通过有没有 $$typeof
属性来断出当前的 element
对象是从数据库来的还是自己生成的。如果没有 $$typeof
这个属性,react
会拒绝处理该元素。
22.React图片懒加载怎么实现的?
懒加载是延迟加载资源(图片....)的一种策略,
React 中可以使用 react-lazyload 插件实现资源的懒加载。
23.React路由传参的方式?
react 路由有三种产地参数的方法:
Props.params 该方法可以传递一个或者多个值。
Query 方法 该方法类似于表单中的get方法,传递参数为明文,但是刷新页面数据会丢失。
State 方法 获取参数需要使用 this.props.match.params.字段名
24.React路由跳转的方式有哪些?
React 跳转路由的4中方法:
<Link/> 标签 在不刷新页面的情况下进行刷新页面 它会渲染一个a标签,to属性是跳转路径,exact 是精准匹配。
Histopy.push 其参数是跳转路径,他也不会刷洗页面。
Redireact组件, 该组件可以重定向到指定路由
Window.location.href 进行跳转,会导致页面刷新。
25.React是如何配置嵌套路由的?
使用<Route /> 标签配置路由
Path= 对应路由名称 element 对应页面名称
默认显示的页面不需要填写路由名称, 子路由不需要不需要使用/ 跳转的时候会带上/符号。
26。说说你对BFC的理解?
官方定义:BFC(Block Formatting Context)块格式化上下文, 是Web页面的可视CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。
27.withRouter的作用?
WithTouter 的作用是假如一个东西不是一个Router,而需要跳转,比如点击logo需要跳转到首页。 在导出组件的时候用white Router包裹 加工组件,使普通组件具备路由组件特有的API
28. React中getDerivedStateFromProps使用方式?
getDerivedStateFromProps 会在调用 render 方法之前调用,即在渲染 DOM 元素之前会调用,并且在初始挂载及后续更新时都会被 调用。
state 的值在任何时候都取决于 props。
getDerivedStateFromProps 的存在只有一个目的:让组件在 props 变化时更新 state。
该方法返回一个对象用于更新 state,如果返回 null 则不更新任何内容。
29.React 如何做性能优化?
避免不必要的渲染
路由懒加载
组件缓存 react.memo
动态路由和动态侧边导航
项目中一些大的本地图片,上传阿里云
减少项目中错误代码
列表渲染添加key
30.说说你对事件循环的理解?
同步任务进入主线程,即主执行栈,异步任务进入任务队列,主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。上述过程的不断重复就事件循环
31. 深拷贝和浅拷贝有什么区别?怎么实现深拷贝?
浅拷贝: 基本数据类型直接拷贝 数据属性,引用数据类型 直接拷贝内存地址,拷贝的和被拷贝的占用的是一个内存地址,这样改变拷贝中的数据,原数据也会发生变化。
深拷贝: 基本数据类型直接拷贝, 引用数据类型的话会开辟一个新的内存地址空间,这样原数据和拷贝的,存储的内存地址不一样,更改数据的话不会相互影响。
深拷贝的实现方式: Json.parse(Json.stringify())
32.现在有一个父组件A, 嵌套一个子组件B,请简述组件A,B组件生命周期的挂载阶段执行流程?
父 ConponentWillMount > 父 render > 子 ComponentWillMount > 子 render >子 ComponenDidMount > 父 ComponentDidMount
33.为什么虚拟DOM能够提升性能?
因为虚拟DOM涉及diff算法,当发生改变时,新旧两棵虚拟DOM树,会进行diff算法对比,只更新发生改变的部分,而不是重新渲染整个页面。所以DOM 能够提升性能。
34.react-redux和redux的区别?
** redux简介:**
redux是react中进行state状态管理的JS库(并不是react插件),一般是管理多个组件中共享数据状态。这个有点像Vue的Vuex状态管 理。
** react-redux简介:** React-Redux是Redux的官方React绑定库。它能够使你的React组件从Redux store中读取数据,并且向store分发actions以更新数据。
①:redux和组件进行对接的时候是直接在组件中进行创建。react-redux是运用Provider将组件和store对接,使在Provider里的所有组件都能共享store里的数据,还要使用connect将组件和react连接。
35. Redux 和 Vuex 有什么区别,它们有什么共同思想吗?
(1) Redux和Vuex区别
-
Vuex改进了Redux中的Action和Reducer函数,以mutations变化函数取代Reducer,无需switch,只需在对应的mutation函数里改变state值即可
-
Vuex由于Vue自动重新渲染的特性,无需订阅重新渲染函数,只要生成新的State即可
-
Vuex数据流的顺序是:View调用store.commit提交对应的请求到Store中对应的mutation函数->store改变(vue检测到数据变化自动渲染)
通俗点理解就是,vuex弱化 dispatch,通过commit进行store状态的一次更变;取消了action概念,不必传入特定的action形式进行指定变更;弱化reducer,基于commit参数直接对数据进行转变,使得框架更加简易;
相同点:
单一的数据源,变化可以预测。
36.redux如何进行异步请求?
在 Redux 中发送异步请求有几种常见的方法。其中一种方法是使用 Redux Thunk 中间件。
然后,在创建 Redux store 的时候,使用 applyMiddleware 函数将 Redux Thunk 中间件传递给 createStore 函数:
接下来,就可以在 action creator 中使用 Redux Thunk 中间件的函数 dispatch 和 getState 来发送异步请求了
37.shouldComponentUpdate如何做子组件性能优化?
当一个组件的props或state变更的时候,React会将最新的返回元素与之前的元素进行对比,以此决定是否有必要更新真实dom,当他们不相同时,React会更新Dom,
即使React 只更新了的Dom节点,重新渲染仍花费了一段时间,在大部分情况下他并不是问题,不过如果他已经慢到让人注意了,你可以通过覆盖声明周期方法, shouldComponentUpdate
来进行提速,说白了就是 shouldComponentUpdate
函数返回的是true的时候,才会触发render 钩子函数。
38.合成事件和原生事件的区别?
原生事件:原生事件,事件处理函数返回 false,可以阻止事件冒泡
合成事件: 封装事件,实现跨平台,把差异封装在底层
将事件全部统一冒泡到 document 再进行触发
可以统一命名,这样子命名符合 react 编程习惯,比如点击事件 onClick,点击事件(捕获阶段)onClickCapture
39. combineReducers的作用是什么?
combineReducers 辅助函数的作用是,把一个由多个不同 reducer 函数作为 value 的 object,合并成一个最终的 reducer 函数,然后就可以对这个 reducer 调用 createStore。
合并后的 reducer 可以调用各个子 reducer,并把它们的结果合并成一个 state 对象。state 对象的结构由传入的多个 reducer 的 key 决定。
40. connect方法的作用?
作用:连接 React 组件与 Redux store。 将store和组件联系到一起,但是它并不会改变它连接的connect组价,而是提供一个经过包裹的connect组件
(1)获取state connect通过context获取 Provider中的store,通过store.getState()获取整个store tree上所有state (2)包装原组件 将state和action通过props的方式传入到原组件内部wrapWithConnect返回一个ReactComponent对象Connect,Connect重新render外部传入的原组件WrappedComponent,并把connect 中传入的mapStateToProps,mapDispatchToProps与组件上原有的props合并后,通过属性的方式传给WrappedComponent (3)监听store tree变化 connect缓存了store tree中state的状态,通过当前state状态和变更前state状态进行比较,从而确定是否调用this.setState()方法触发Connect及其子组件的重新渲染
41. react单页面应用程序的优缺点?
优点:
良好的交互体验,
良好的前后端工作分离模式
减轻服务器压力
缺点:
首屏加载慢
42.React如何解决防抖节流?
节流: 一段时间内只运行一次,若这段时间内重复触发,只有一次生效。
防抖: 一段时间后在执行该事件,若在这段时间内重复触发,则重新计时
解决有react 第三方库 lodash
43.Redux 中store 常用的api有哪些?
CrateStore() 创建store
Store.dispatch() 派发action 传递给store
Store.getstate() 可以获取到store 里面的数据
Store.subscribe() 订阅store的改变,只有store 进行改变,这个方法就执行。
44. React中hooks是什么作用?
hook就是 React 函数组件的副效应解决方案,用来为函数组件引入副效应。 函数组件的主体只应该用来返回组件的 HTML 代码,所有的其他操作(副效应)都必须通过钩子引入。React Hooks 的设计目的,就是加强版函数组件,完全不使用"类",就能写出一个全功能的组件。
45.说说你对高阶组件的理解?应用场景有哪些?
高阶函数,至少满足下列一个条件的函数:
接受一个或多个函数作为输入
输出一个函数
react 函数中,高阶组件即接受一个或者多个组件作为参数并且返回一个组件,本质也就是一个函数,并不是组件。
46.useMemo,memo, useCallback如何提升性能呢?
useMemo 他可以对数值进行缓存,如果你的依赖没有改变,则下一次调用时,读取上一次的缓存,从而提升性能。
userCallback 是用来缓存函数的,如果子组件有一个方法,用来修改父组件的数据,那么每一次执行,父组件都要重新渲染一次方法给子组件,子组件又要重新渲染,这时候就可以使用 userCllback 来进行缓存
memo 是顶层的Api方法,它可以减少子组件的重复渲染次数,从而提升组件渲染性能。
47.说说对React rfcs 的理解?应用场景?
React 中的rfcs ,允许我们访问DOM节点或 在render 方法中创建React 元素。
使用场景:
对DoM元素的焦点控制,内容控制,
对dom 元素的内容设置及媒体播放
对DOM 元素的操作和对组件实例的操作
48.说说你对useEffect的理解,可以模拟哪些生命周期?
react提供了hooks,因此函数组件可以使用hooks进行状态管理并且也可以用使用userEffect 模拟class组件的生命周期
useEffect 接收两个参数 第一个参数是你要进行的异步操作,第二个参数是一个数组,用来给出Effect 的依赖项,只要这个数组发生变化,useEffect 就会执行
useEffect 模拟了componentDidmount componentDidUpdate componentWillunMount
49.说说React中setState和replaceState的区别?
setState 会将新的状态合并到原有的状态中。并重新渲染组件
replace State 是完全替换原来的状态,相当于赋值,将原来的state 替换为另一个对象,如果新状态属性减少,那么state 中就没有这个状态了。
50.说说react中onClick绑定后的工作原理?
react 绑定onClick 后 会把react 上注册的事件最终都绑定到document 这个DOm上,而不是react组件对应的Dom ,这样能够减少内存开销就是因为所有的事件都绑定到document 上,其他结点没有绑定事件,
React 自身实现了一套冒泡机制,通过队列的方式,从触发组件向父组件回溯,然后调用他们JSX中定义的callback
51.说说你对fiber架构的理解?解决了什么问题
fiber架构改变了以前react同步的组件渲染机制,使原来同步渲染的组件如今能够异步化,可中断渲染,执行更高优先级的任务,用户体验更好。
解决了什么问题:
fiber的引入主要是为了解决在网页里面用户和网页应用进行交互问题:github 在react16以前的版本中,组件渲染是同步的,若是组件包含不少子组件,渲染的时间就比较长,在组件渲染的过程中没法打断,会导致这期间用户没法与页面进行交互
全部的任务都是按照前后顺序,没有优先级可言,这样就会导致优先级低的任务没办法在优先级高的任务前执行。
52.说说对Redux中间件的理解?常用的中间件有哪些?
Redux中,中间件就是放在就是在dispatch过程,在分发action进行拦截处理
前面我们了解到了Redux整个工作流程,当action发出之后,reducer立即算出state,整个过程是一个同步的操作 那么如果需要支持异步操作,或者支持错误处理、日志监控,这个过程就可以用上中间件,其本质上一个函数,对store.dispatch方法进行了改造,在发出 Action和执行 Reducer这两步之间,添加了其他功能
常用的redux中间件,如: redux-thunk:用于异步操作 redux-logger:用于日志记录
中间件都需要通过applyMiddlewares进行注册,作用是将所有的中间件组成一个数组,依次执行然后作为第二个参数传入到createStore中
53.什么是强缓存和协商缓存?
强缓存: 他不用向服务器发送请求, 他直接可以从缓存里面读取数据,在chrome 控制台的network 选项中可以看到该请求返回200的状态码。
协商缓存: 它会向服务器发送请求,服务器会根据这个请求的request header 的一些参数来判断是不是协商缓存,如果是的话他就带新的 response header 通知浏览器再去通过浏览器从本地中读取资源,协商缓存最终由服务器决定是否使用缓存,即客户端与服务器之间存在一次通信。
54.说说你对@reduxjs/toolkit的理解?和react-redux有什么区别?
@reduxjs/toolkit 官方强烈推荐,是个高效的Redux开发工具集,它旨在成为标准的redux 逻辑开发模式,使用 @reduxjs/toolkit 都可以优化你的代码,使其更可维护
react-redux 官方推出的redux 库,react-redux 将所有的组件分为两大类: UI组件和容器组件,其中容器组件包裹着UI组件,构成父子关系,容器组件负责redux 交互,里面使用redux API函数,UI组件负责页面渲染,不使用任何redux API ,容器组件会给UI组件传递redux 中保存的状态和操作状态的方法。
55.知道react里面的createPortal么,说说其使用场景?
Protal 将提供一种将子组件渲染到DOM结点中的方式,该结点存在于DOm组件的层次结构之外。
因此 Portal 适合脱离文档流的组件, 特别是 : position:absolute 与 position:fixed 的组件,比如模态框,通知,警告等。
56.说说AMD、CMD、commonJS模块化规范的区别?
CommonJS是服务器端js模块化的规范,NodeJS是这种规范的实现
AMD(异步模块定义)和CMD(通用模块定义)都是浏览器端js模块化的规范。requireJS遵循的是AMD,seaJS遵循的是CMD
这三个都是为Js模块化加载而生的,使模块能够按需加载,使系统同庞杂的代码得到组织和管理。模块化的管理代码使多人开发得到了更好的合作
57.context状态树是怎么运行的?
在父组件中我们通过createContext 创建一个空对象,在父组件的最外层我们使用Provider 包裹数据,通过value 绑定要传递的对象数据
在嵌套子组件中,我们又两种方式获取数据:
(1) 我们可以使用Customer 标签,在标签中绑定一个箭头函数,函数的形参context就是value传递的数据
(2) class 组件中我们可以定义static contextType = context 对象,组件中直接使用this.context获取数据
58.Redux 实现原理 和 核心代码
实现原理:
React 的组件需要获取或者修改页面的数据,通过Dispatch 方法调用actions 进入到Reducer函数中修改state的数据,state更新后,通知组件更近页面即可
核心代码:
createStore 方法 用于创建公共区域
创建Reducer 纯函数 接收state,action 分别表示数据和操作state的方法,返回state数据给页面
把reducer 作为createState 的参数抛出
在需要的页面通过导入store 通过 store.getStare 获取数据 通过 store.dispatch 触发action修改
59.useEffect的依赖为引用类型如何处理?
useEffect的依赖为引用数据类型,可能会导致监听不触发,原因就是监听的同一个地址的时候,对象本身地址没有变,所以监听的结果就是认为数据并没有改变从而不直接调用。
解决方法
如果数据是对象的话,可以监听对象里面的值,值是基本数据类型,如果值改变了,那么可以监听执行
在去修改对象和数据的时候,使用深拷贝或者浅拷贝,这样地址发生改变可以监听执行
可以转成字符串,通过JSON.stringify(),监听字符串这样的,这样改变也会执行。
60.React的props.children使用map函数来遍历会收到异常显示,为什么?应该 如何遍历?
在react 中 props.children 不一定是数组
有三种可能 : 1.当前组件没有子节点数据类型就是undefined, 2.有一个子节点数据类型就是object 。 3 .有多个子节点的时候才会是array ,只有在多个节点的时候才可以直接调用map方法,react提供了一个react.children.map()方法,可以安全遍历子节点对象。
61.谈谈你对immutable.js的理解?
Immutable Data 就是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改、添加或删除操作都会返回一个新的 Immutable 对象。 Immutable 实现原理是持久化数据结构(Persistent Data Structure),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。 为了避免深度拷贝(deep Copy)把所有节点都复制一遍带来的性能损耗,Immutable 使用了共享结构(Structural Sharing),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。
62.redux中同步action与异步action最大的区别是什么?
同步action:执行了dispatch函数之后,对应的reducer纯函数立即得到执行,reducer执行完了之后,state立即就改变了,此时用store.getState函数,取到的是最新的state值; 异步action:原则上redux并没有提供异步action的处理方案,异步的action需要依赖第三方的中间件解决,dispatch了一个异步action之后,目标state并不会立即响应,而是要看异步函数内部的逻辑,来决定state什么时候响应
63.在使用redux过程中,如何防止定义的action-type的常量重复?
ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。 Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对象 Symbol函数可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
64.移动端1像素的解决方案?
移动端 1 像素问题指的是在高清屏幕下,使用 1 像素的边框或者线条会出现模糊或者变粗的问题。解决方案有以下几种:
-
使用 viewport + rem 方案,将 1px 转换为对应的 rem 值,再通过 CSS 样式设置边框或者线条的宽度,可以避免 1 像素问题。
-
使用 CSS3 的 transform:scale() 缩放属性,将元素缩小至 0.5px,再放大至 2 倍大小,可以解决 1 像素问题。
-
使用 border-image 属性,将边框图片设置为 1 像素宽度,可以解决 1 像素问题。
-
使用 box-shadow 属性,将阴影设置为 1 像素宽度,可以模拟出 1 像素边框的效果,同时避
65 ReactDOM.render是如何串联渲染链路的?
ReactDOM.render 调用栈大致可以拆分成如下三个阶段: 初始化阶段、render阶段、commit阶段
在初始化阶段,整个初始化的工作过程都是在为render 阶段做准备。在render阶段由 ReactDOM.render 发起的首屏渲染的场景下,它触发的就是 performSyncWorkOnRoot。它开启的就是 render 阶段;finishSyncRoot标志着render方法的结束,在这个过程中,穿插了大量了beginWork、completeWork调用(这两个方法串联起来就是一个模拟递归的过程),这个两个方法就是render的工作内容。commit阶段完成了对 ReactDOM.render 调用栈的分析。表面上剖析的是首次渲染的渲染链路,实际上将包括同步模式下的挂载、更新链路都串联了一遍。
66.理解React中的栈调和
调和是指虚拟DOM映射到真实DOM的过程。调和过程包括了组件的挂载、更新和卸载。调和不等于Diff,但是由于Diff是调和最具代表性的一环,所以讨论调和的时候,通常是在讨论Diff; Diff算法是逐层比较同一层的节点,只对同一类的标签进行Diff比较,设置key可以帮助React复用节点提高渲染性能。
67.前端跨域的解决方案?
在前端开发中,跨域是指在浏览器环境下,当前网页的请求无法访问其他域下的资源,主要是由于浏览器的同源策略所限制。同源策略要求请求的协议、域名和端口必须完全相同,否则就会出现跨域问题。
以下是一些常见的前端跨域解决方案:
-
JSONP(JSON with Padding): JSONP是一种利用
<script>
标签进行跨域请求的方法。通过在请求URL中添加一个回调函数参数,服务器在返回数据时将数据包裹在该回调函数中,从而实现跨域数据的获取。 -
CORS(Cross-Origin Resource Sharing): CORS是一种现代浏览器支持的跨域解决方案。服务器可以在响应头中设置
Access-Control-Allow-Origin
字段来指定允许访问资源的域名。通过服务器设置合适的CORS头,前端可以在跨域请求时得到服务器的许可,从而实现跨域通信。 -
代理服务器: 可以设置一个代理服务器,将前端请求发送到同源的后端服务器,再由后端服务器去请求跨域的资源,并将结果返回给前端。这样前端请求的是同源的资源,避免了跨域问题。
-
WebSocket: WebSocket是一种双向通信协议,可以在不受同源策略限制的情况下进行跨域通信。通过在客户端和服务器之间建立WebSocket连接,前端可以与任意域的服务器进行实时通信。
-
反向代理: 可以使用反向代理服务器,将前端请求代理到目标服务器,并将响应返回给前端。这样前端请求的是同源的资源,而代理服务器则负责与目标服务器进行跨域通信。
-
PostMessage: HTML5的
postMessage
方法允许在跨域的窗口之间安全地传递消息。前端可以通过postMessage
方法发送消息给目标窗口,目标窗口监听并处理该消息。
68.说说reduce方法的作用?自己手动封装一个reduce,写出其核心代码?
·reduce()
是JavaScript数组的高阶函数之一,它用于对数组中的每个元素进行累积操作,并最终返回一个结果。它接受一个回调函数作为参数,该回调函数可以接受四个参数:累积值(初始值或上一次回调函数的返回值)、当前值、当前索引和原始数组。
手动封装一个?
function reduce(array, callback, initialValue) {
let accumulator = initialValue !== undefined ? initialValue : array[0];
for (let i = initialValue !== undefined ? 0 : 1; i < array.length; i++) {
accumulator = callback(accumulator, array[i], i, array);
}
return accumulator;
}
69.函数组件中如何使用useReducer?
useReducer 钩子用来存储和更新状态,有点类似 useState 钩子。在用法上,它接收一个reducer函数作为第一个参数,第二个参数是初始化的state。useReducer最终返回一个存储有当前状态值的数组和一个dispatch函数,该dispatch函数执行触发action,带来状态的变化。这其实有点像redux,不过还是有一些不同
70.说说你对TypeScript中泛型的理解及其应用场景?
什么是泛型
泛型的本质是参数化类型,通俗的将就是所操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法的创建中,分别成为泛型类,泛型接口、泛型方法。
为什么使用泛型
TypeScript 中不建议使用 any 类型,不能保证类型安全,调试时缺乏完整的信息。
TypeScript可以使用泛型来创建可重用的组件。支持当前数据类型,同时也能支持未来的数据类型。扩展灵活。可以在编译时发现你的类型错误,从而保证了类型安全
71.说一说设备像素、css像素、设备独立像素、dpr、ppi之间的区别?
css像素:
px是一个相对单位,相对的是设备像素(device pixel)
一般情况,页面缩放比为1,1个CSS像素等于1个设备独立像素
在页面进行缩放操作也会 引起css中px的变化,假设页面放大一倍,原来的 1px 的东西变成 2px,在实际宽度不变的情况下1px 变得跟原来的 2px 的长度(长宽)一样了(元素会占据更多的设备像素)
px会受到下面的因素的影响而变化:
每英寸像素(PPI) 设备像素比(DPR)
设备像素:
设备像素(device pixels),又称为物理像素
指设备能控制显示的最小物理单位,不一定是一个小正方形区块,也没有标准的宽高,只是用于显示丰富色彩的一个“点”而已
从屏幕在工厂生产出的那天起,它上面设备像素点就固定不变了,单位为pt
设备独立像素:
设备独立像素(Device Independent Pixel):与设备无关的逻辑像素,代表可以通过程序控制使用的虚拟像素,是一个总体概念,包括了CSS像素
比如我们会说“电脑屏幕在 2560x1600分辨率下不适合玩游戏,我们把它调为 1440x900”,这里的“分辨率”(非严谨说法)指的就是设备独立像素
一个设备独立像素里可能包含1个或者多个物理像素点,包含的越多则屏幕看起来越清晰
dpr:
dpr(device pixel ratio),设备像素比,代表设备独立像素到设备像素的转换关系
ppi:
ppi (pixel per inch),每英寸像素,表示每英寸所包含的像素点数目,更确切的说法应该是像素密度。数值越高,说明屏幕能以更高密度显示图像
72.说说webpack proxy的工作原理?为什么能够解决跨域?
webpack proxy,即webpack提供的代理服务,
基本行为就是接收客户端发送的请求后转发给其他服务器
想要实现代理首先需要一个中间服务器,webpack中提供服务器的工具为webpack-dev-server
工作原理:
通过设置webpack proxy实现代理请求后,相当于浏览器与服务端中添加一个代理者
当本地发送请求的时候,代理服务器响应该请求,并将请求转发到目标服务器,目标服务器响应数据后再将数据返回给代理服务器,最终再由代理服务器将数据响应给本地
在代理服务器传递数据给本地浏览器的过程中,两者同源,并不存在跨域行为,这时候浏览器就能正常接收数据