当前位置: 首页 > Web前端 > HTML

阿里前端二面react面试题(边面边更)

时间:2023-03-29 12:26:29 HTML

shouldComponentUpdate有什么用?它为什么如此重要?当组件状态数据或属性数据更新时,组件将进入存在期,视图将被渲染和更新。在生命周期方法shouldComponentUpdate中,允许选择退出某些组件(及其子组件)的协调过程。协调的最终目标是根据新状态以最有效的方式更新UI。如果我们知道UI的某个部分不会改变,那么React就没有理由确定它是否应该更新渲染。通过在shouldComponentUpdate方法中返回false,React将使当前组件及其所有子组件保持与当前组件相同的状态。React组件生命周期的不同阶段是什么?组件生命周期中有四个不同的阶段:初始化:在此阶段,组件准备好设置其初始化状态和默认属性。挂载:react组件已准备好挂载到浏览器DOM中。此阶段包括componentWillMount和componentDidMount生命周期方法。更新:在这个阶段,组件以两种方式更新,发送新的道具和状态。此阶段包括shouldComponentUpdate、componentWillUpdate和componentDidUpdate生命周期方法。卸载:在这个阶段,不再需要该组件并将其从浏览器DOM中卸载。此阶段包含componentWillUnmount生命周期方法。除了上面常用的四种生命周期,还有一个错误处理阶段:发生时,该组件将被调用。此阶段包含componentDidCatch生命周期方法。React的虚拟DOM和Diff算法的内部实现传统的diff算法的时间复杂度是O(n^3),这在前端渲染中是无法接受的。为了降低时间复杂度,react的diff算法做了一些折衷,放弃了最优解,最终将时间复杂度降低到O(n)。那么reactdiff算法做了哪些妥协呢?,参考如下:treediff:只比较同层的dom节点,忽略dom节点的跨层移动。当发现该节点不存在时,该节点及其子节点将被彻底删除,不再用于进一步的比较。这样只需要遍历一次树就可以完成整个DOM树的比较。这意味着如果dom节点跨层移动,react将删除旧节点并生成新节点而不会重复使用。Componentdiff:如果不是同类型的component,则删除旧的component,创建一个新的component。elementdiff:对于同一层级的一组子节点,需要通过唯一的id来区分。如果没有id区分,一旦有插入动作,就会导致插入位置之后的所有列表重新渲染,这就是为什么在渲染列表的时候要用一个唯一的key。生命周期方法的调用顺序是什么?React生命周期分为三大周期11个阶段,生命周期方法的调用顺序如下。(1)创建期的五个阶段,调用方法的顺序如下。getDefaultProps:定义默认属性数据。getInitialState:初始化默认状态数据。componentWillMount:组件即将被构建。渲染:渲染组件。componentDidMount:组件构建完成(2)在存在期的五个主要阶段,调用方法的顺序如下。componentWillReceiveProps:组件即将接收新的prop数据。shouldComponentUpdate:确定组件是否应该更新。componentWillUpdate:组件即将更新。渲染:渲染组件。componentDidUpdate:组件更新完成。(3)在销毁期的某个阶段,调用componentWillUnmount方法表示组件即将销毁。您在哪个生命周期中发出Ajax请求?为什么?Ajax请求应该写在组件创建的第五阶段,即componentDidMount生命周期方法中。理由如下。在创建的其他阶段,组件尚未呈现。在存在期的五个阶段,不能保证生命周期方法一定会被执行(比如通过shouldComponentUpdate方法优化更新等)。销毁期间,组件即将销毁,请求数据变得无意义。所以在这些阶段发出Ajax请求显然不是最好的选择。在组件挂载之前,Ajax请求不会完成。如果这个时候再请求,就意味着在组件挂载之前更新状态(比如执行setState),这通常是行不通的。在componentDidMount方法中,执行Ajax可以保证组件已经挂载,组件可以正常更新。为什么使用React.Children.map(props.children,()=>)而不是props.children.map(()=>)?因为不能保证props.children会是一个数组。以下面的代码为例。

Thereareclassfront-endnetwork

在父组件内部,如果尝试使用props.children.map映射子对象,会抛出错误,因为props.children是一个对象,而不是数组。如果有多个孩子,React会将props.children变成一个如下所示的数组。

优客前端网

前端技术学习平台

;//不建议使用下面的方法,会报错在这种情况下抛出。classParentextendsComponent{render(){return
{this.props.children.map((obj)=>obj)}
;}}推荐使用下面的方法,避免抛出前面case的错误。classParentextendsComponent{render(){return
{React.Children.map(this.props.children,(obj)=>obj)}
;Reactdiff算法的详细答案参考前端高级面试题我们知道React会维护两个虚拟DOM,那么如何比较,如何判断,做出最优解呢?这里使用diff算法计算出VirtualDOM真正变化的部分,只对这部分进行nativeDOM操作,而不是重新渲染整个页面。传统的diff算法通过循环递归依次比较节点,算法复杂度达到O(n^3),其中n为树中的节点数。这有多可怕?-如果要显示1000个节点,则必须进行数亿次比较。.即使有能够执行30亿条命令的CPU,也很难在一秒钟内计算出差异。React的diff算法什么是reconciliation?将虚拟DOM树转换为实际DOM树的最小操作过程称为协调。什么是Reactdiff算法?diff算法是reconciliation的具体实现。diff策略React使用三种策略将O(n^3)复杂度转化为O(n)复杂度策略一(treediff):DOM节点在WebUI中跨层级的移动是极其罕见的,可以忽略不计,因为交叉DOM节点的层级移动可以忽略不计,React使用updateDepth来控制VirtualDOM树的层级,即同层。在比较过程中,如果发现该节点已经不存在,则将其彻底删除。对比其他地方,只需要遍历一次树。策略2(componentdiff):类相同的两个组件生成相似的树结构,类不同的两个组件生成不同的树结构。策略三(元素diff):对于同一层级的一组子节点,通过唯一id来区分。treediffReact通过updateDepth控制VirtualDOM树的层级。对于树级比较,两棵树只比较同一级别的节点。如果该节点不存在,则完全删除该节点及其子节点,不再进行进一步比较。只需要遍历一次就可以完成整个DOM树的比较。那么问题来了,如果对DOM节点进行了跨级操作,diff会发生什么变化呢?答:diff简单的考虑了同层节点的位置变化。如果是跨层,则只有创建节点和删除节点的操作。如上图所示,将重新创建以A为根节点的整棵树,而不是移动。所以官方建议不要对DOM节点进行跨级操作。您可以通过CSS隐藏和显示节点,而不是实际删除和添加它们。DOM节点组件diffReact有三种比较不同组件的策略。对于同类型的两个组件,只要按照原来的策略(层级比较)继续比较VirtualDOM树即可。对于同一类型的两个组件,当组件A变为组件B时,VirtualDOM可能根本没有变化。如果知道这一点(VirtualDOM在转换过程中不会发生变化),就可以节省大量的计算时间,所以用户可以使用shouldComponentUpdate()来判断是否需要判断计算。对于不同类型的组件,将一个(待改变的)组件判断为脏组件(dirtycomponent),从而替换整个组件的所有节点。注意:如果组件D和组件G的结构相似,但React判断它们是不同类型的组件,则不会比较结构,但会删除组件D及其子节点,组件G及其子节点将被创建。elementdiff当节点处于同一层次时,diff提供三种节点操作:删除、插入和移动。插入:组件C不在集合(A,B)中,需要插入。删除:组件D在集合(A,B,D)中,但是D的节点已经改变,不能被复用和更新,所以需要删除旧的D。然后创建一个新的。组件D以前在集合(A,B,D)中,但集合变成了新集合(A,B),需要删除D。Move:组件D已经在集合(A,B,C,D)中,更新集合时,D没有更新,只是位置发生变化,比如新的集合(A,D,B,C),D在secondOne中,不需要像传统diff一样把oldset的第二个B和newset的第二个D比较,删掉第二个位置的B,在第二个位置插入D,但是(对于同一组中的同级子节点)添加一个唯一键来区分,移动即可。尽量减少diff的不足和需要优化的地方,比如把最后一个节点移到链表的头部。当节点数量过多或者更新操作过于频繁时,都会影响React的渲染性能。在ReactNative中,如何解决adbdevicescannotbefound无法连接到你的设备?使用Genymotion时,首先需要在SDK的platform-tools中添加环境变量,然后在Genymotion中点击Setting,选择ADB标签,点击UsecustomAndroidSDKtools,浏览本地SDK所在位置,点击OK按钮。好的。启动虚拟机后,在cmd中输入adbdevices查看设备。调用setState后会发生什么在代码中调用setState函数后,React会将传递的参数与之前的状态合并,然后触发所谓的协调过程(Reconciliation)。在协调过程之后,React将以一种相对高效的方式根据新的状态构建React元素树,并开始重新渲染整个UI界面。React拿到元素树后,React会计算新旧树的差异,然后根据差异最小化并重新渲染界面。通过diff算法,React可以准确地指导哪些位置发生了变化以及应该如何变化,从而确保按需更新而不是完全重新渲染。setState时,React会为当前节点创建一个updateQueue的更新队列。然后将触发对帐过程。在此过程中,将使用一种称为Fiber的调度算法开始生成新的Fiber树。Fiber算法最大的特点就是可以异步、可中断地执行。然后ReactScheduler会根据优先级优先执行优先级高的节点,具体执行doWork方法。在doWork方法中,React会执行updateQueue中的方法获取新的节点。然后比较新旧节点,并用更新、插入和替换标记旧节点。当前节点的doWork完成后,会执行performUnitOfWork方法获取新的节点,然后重复上述过程。当所有节点都完成doWork后,会触发commitRoot方法,React进入commit阶段。在commit阶段,React会为每个节点根据之前的Tag一次性更新整个dom元素。ref作为函数有什么好处?方便react在重新渲染时销毁组件和清除refs以防止内存泄漏。为什么虚拟dom会提高性能?虚拟dom相当于在js和真实dom之间加了一个缓存,利用domdiff算法避免不必要的dom操作,从而提高性能。具体实现步骤如下:使用JavaScript对象结构来表示DOM树的结构;然后用这棵树构建一个真正的DOM树,当状态改变时将它插入到文档中,重建一个新的对象树。然后将新树与旧树进行比较,记录两棵树的差异,将2中记录的差异应用到步骤1中构建的真实DOM树上,更新视图上的虚拟DOM。它会提高性能吗?许多人认为虚拟DOM肯定会提高性能并且更快。其实这种说法有点片面,因为虚拟DOM虽然会减少DOM操作,但是无法避免DOM操作。它的优势在于diff算法和批处理策略。收集DOM操作一次性改变真实DOM,但是在第一次渲染时,虚拟DOM会多一层计算,会消耗一些性能,所以可能比html渲染慢注意虚拟DOM是其实就是给我们找最短最近的路径,不是说比DOM操作快,而是路径最简单。这段代码有什么问题?类App扩展组件{constructor(props){super(props);this.state={username:"友家前端网络",msg:"",};}render(){return
{this.state.消息
;}componentDidMount(){this.setState((oldState,props)=>{return{msg:oldState.username+"-"+props.intro,};});}}render(,ickt)页面正常输出“优客前端网-前端技术专业学习平台”。但是这种写法很少用到,也不是常用的写法。React允许将一个函数传递给setState方法,该方法接收之前的状态和属性数据并返回一个需要修改的状态对象,就像我们上面所做的那样。不仅没有问题,如果当前状态是根据之前的状态(state)和属性修改的,建议使用这种写法。传递给setstate函数的第二个参数的目的是什么?第二个参数是一个函数,当调用setState函数并且组件开始重新渲染时会调用该函数。您可以使用此功能来监视渲染是否完成。this.setstate({username:"优客前端网络",},()=>console.log("重新渲染成功。"));react-router中的标签是什么与相比,Link组件避免了不必要的重新渲染。React如何检查和更改数据?Model发生变化后(可能调用setState),触发虚拟dom的更新,然后使用diff算法与虚拟DOM和RealDOM进行比较,检查更新了哪个dom节点,然后渲染realdom高阶组件。静态方法丢失的问题(必须复制静态方法)。refs属性不能透传(如果发送的是高阶组件创建的组件,给元素添加ref引用,那么ref指向最外层的容器组件实例,而不是被包裹的WrappedComponent组件。)反向继承不能保证完整的子组件树被解析。React组件有两种形式,即类类型和函数类型(无状态组件)。我们知道反向继承的渲染劫持可以控制WrappedComponent的渲染过程,也就是说我们可以在这个过程中对elementstree、state、props或者render()的结果进行各种操作。但是如果渲染元素树中包含函数类型的组件,那么就无法操作该组件的子组件。React中的受控组件和非受控组件是什么?(1)当受控组件使用表单收集用户输入时,