当前位置: 首页 > 后端技术 > Node.js

帮助大家理解preact的源码(三)

时间:2023-04-03 14:38:10 Node.js

对回收的处理在preact中,回收调用了两个方法。dom节点的回收一般调用recollectNodeTree,组件的回收调用unmountComponent。preactreusedom的秘诀在于,当一个组件要卸载时,只会从父节点卸载该组件的根节点,该组件的完整dom依然存在,卸载的组件会保存在components中目的。创建组件时,通过nodeName获取对应的dom节点树,挂载到组件实例的inst.nextBase上,然后diffnextBase和renderingComponent时渲染的新虚拟dom树。相关主要代码如下:functioncreateComponent(Ctor,props,context){letlist=components[Ctor.name],inst;if(Ctor.prototype&&Ctor.prototype.render){inst=newCtor(props,context);Component.call(inst,props,context);}else{//对应的功能组件inst=newComponent(props,context);inst.constructor=Ctor;inst.render=doRender;}if(list){for(leti=list.length;i--;){if(list[i].constructor===Ctor){inst.nextBase=list[i].nextBase;list.splice(i,1);休息;}}}returninst;}setState改变组件上的状态,然后将要渲染的组件放在一个数组中,在下一个事件循环中渲染:setState:functionsetState(state,callback){lets=this.状态;如果(!this.prevState)this.prevState=extend({},s);扩展(s,typeofstate==='function'?state(s,this.props):state);如果(回调)(这个._renderCallbacks=t他的._renderCallbacks||[]).push(回调);排队渲染(这个);},functionenqueueRender(component){//component._dirty为false,items可以渲染if(!component._dirty&&(component._dirty=true)&&items.push(component)==1){(options.debounceRendering||推迟)(重新渲染);//Render是异步执行的,执行render方法的组件中的_dirty设置为true}},functionrerender(){letp,list=items;项目=[];while(p=list.pop()){if(p._dirty)renderComponent(p);}}事件的preact处理为了减少增减事件对性能和内存的影响,preact在对dom做事件监听的时候增加了代理功能functionsetAccessor(node,name,old,value,isSvg){//...if(name[0]=='o'&&name[1]=='n'){letuseCapture=name!==(name=name.replace(/Capture$/,''));name=name.toLowerCase().substring(2);if(value){if(!old)node.addEventListener(name,eventProxy,useCapture);}else{节点。removeEventListener(名称,事件代理,useCapture);}(node._listeners||(node._listeners={}))[name]=value;}//...}functioneventProxy(e){returnthis._listeners[e.type](options.event&&options.event(e)||e);}fiber(个人理解)从上面的源码阅读可以看出,react最大的性能问题在于递归diff。react中的shouldCompnentUpdate和PureComponent也是为了缓解这个问题。但是当应用比较大的时候,高层组件的diff很容易导致动画掉帧。光纤的出现就是为了解决这个问题。reactfiber将计算工作分割成多个小块,可以让整个计算工作挂起、挂起或重启。为不同类型的更新分配优先级。当触发动画或用户交互时,可以先暂停低优先级的更新工作以保证动画的流畅性,等待所有的渲染和计算任务完成后再提交DOM更新。参考https://calendar.perfplanet.c...https://reactjs.org/docs/impl...https://segmentfault.com/a/11...https://www.w3ctech.com/topic...https://zhuanlan.zhihu.com/p/...https://github.com/acdlite/re...