当前位置: 首页 > news >正文

建设网站 软件auto post wordpress

建设网站 软件,auto post wordpress,塘厦镇网站建设,网站建设的目的和目标前言 简单说下为什么React选择函数式组件#xff0c;主要是class组件比较冗余、生命周期函数写法不友好#xff0c;骚写法多#xff0c;functional组件更符合React编程思想等等等。更具体的可以拜读dan大神的blog。其中Function components capture the rendered values这句…前言 简单说下为什么React选择函数式组件主要是class组件比较冗余、生命周期函数写法不友好骚写法多functional组件更符合React编程思想等等等。更具体的可以拜读dan大神的blog。其中Function components capture the rendered values这句十分精辟的道出函数式组件的优势。 但是在16.8之前react的函数式组件十分羸弱基本只能作用于纯展示组件主要因为缺少state和生命周期。本人曾经在hooks出来前负责过纯函数式的react项目所有状态处理都必须在reducer中进行所有副作用都在saga中执行可以说是十分艰辛的经历了。在hooks出来后我在公司的一个小中台项目中使用落地效果不错代码量显著减少的同时提升了代码的可读性。因为通过custom hooks可以更好地剥离代码结构不会像以前类组件那样在cDU等生命周期堆了一大堆逻辑在命令式代码和声明式代码中有一个良性的边界。 useState在React中是怎么实现的 Hooks take some getting used to — and especially at the boundary of imperative and declarative code. 如果对hooks不太了解的可以先看看这篇文章:前情提要十分简明的介绍了hooks的核心原理但是我对useEffectuseRef等钩子的实现比较好奇所以开始啃起了源码下面我会结合源码介绍useState的原理。useState具体逻辑分成三部分mountStatedispatch updateState hook的结构 首先的是hooks的结构hooks是挂载在组件Fiber结点上memoizedState的 //hook的结构 export type Hook {memoizedState: any, //上一次的statebaseState: any, //当前statebaseUpdate: Updateany, any | null, // update funcqueue: UpdateQueueany, any | null, //用于缓存多次actionnext: Hook | null, //链表 };renderWithHooks 在reconciler中处理函数式组件的函数是renderWithHooks其类型是 renderWithHooks(current: Fiber | null, //当前的fiber结点workInProgress: Fiber, Component: any, //jsx中用调用的函数props: any,refOrContext: any,nextRenderExpirationTime: ExpirationTime, //需要在什么时候结束 ): any在renderWithHooks核心流程如下 //从memoizedState中取出hooks nextCurrentHook current ! null ? current.memoizedState : null; //判断通过有没有hooks判断是mount还是update两者的函数不同 ReactCurrentDispatcher.current nextCurrentHook null? HooksDispatcherOnMount: HooksDispatcherOnUpdate; //执行传入的type函数 let children Component(props, refOrContext); //执行完函数后的dispatcher变成只能调用context的 ReactCurrentDispatcher.current ContextOnlyDispatcher;return children;useState构建时流程 mountState 在HooksDispatcherOnMount中useState调用的是下面的mountState作用是创建一个新的hook并使用默认值初始化并绑定其触发器因为useState底层是useReducer所以数组第二个值返回的是dispatch。 type BasicStateActionS (S S) | S;function mountStateS(initialState: (() S) | S, ){const hook mountWorkInProgressHook(); //如果入参是func则会调用但是不提供参数带参数的需要包一层if (typeof initialState function) {initialState initialState();} //上一个state和基本(当前)state都初始化hook.memoizedState hook.baseState initialState;const queue (hook.queue {last: null,dispatch: null,eagerReducer: basicStateReducer, // useState使用基础reducereagerState: (initialState: any),}); //返回触发器const dispatch: Dispatch//useState底层是useReducer所以type是BasicStateAction(queue.dispatch (dispatchAction.bind(null,//绑定当前fiber结点和queue((currentlyRenderingFiber: any): Fiber),queue,): any));return [hook.memoizedState, dispatch]; }mountWorkInProgressHook 这个函数是mountState时调用的构建hook的方法在初始化完毕后会连接到当前hook.next如果有的话 function mountWorkInProgressHook(): Hook {const hook: Hook {memoizedState: null,baseState: null,queue: null,baseUpdate: null,next: null,};if (workInProgressHook null) {// 列表中的第一个hookfirstWorkInProgressHook workInProgressHook hook;} else {// 添加到列表的末尾workInProgressHook workInProgressHook.next hook;}return workInProgressHook; }dispatch分发函数 在上面我们提到useState底层是useReducer所以返回的第二个参数是dispatch函数其中的设计十分巧妙。 假设我们有以下代码: 相关参考视频讲解进入学习 const [data, setData] React.useState(0) setData(first) setData(second) setData(third)在第一次setData后 hooks的结构如上图 在第二次setData后 hooks的结构如上图 在第三次setData后 hooks的结构如上图 在正常情况下是不会在dispatcher中触发reducer而是将action存入update中在updateState中再执行但是如果在react没有重渲染需求的前提下是会提前计算state即eagerState。作为性能优化的一环。 function dispatchActionS, A(fiber: Fiber,queue: UpdateQueueS, A,action: A, ) {const alternate fiber.alternate;{flushPassiveEffects();//获取当前时间并计算可用时间const currentTime requestCurrentTime();const expirationTime computeExpirationForFiber(currentTime, fiber);const update: UpdateS, A {expirationTime,action,eagerReducer: null,eagerState: null,next: null,};//下面的代码就是为了构建queue.last是最新的更新然后last.next开始是每一次的action// 取出lastconst last queue.last;if (last null) {// 自圆update.next update;} else {const first last.next;if (first ! null) {update.next first;}last.next update;}queue.last update;if (fiber.expirationTime NoWork (alternate null || alternate.expirationTime NoWork)) {// 当前队列为空我们可以在进入render阶段前提前计算出下一个状态。如果新的状态和当前状态相同则可以退出重渲染const lastRenderedReducer queue.lastRenderedReducer; // 上次更新完后的reducerif (lastRenderedReducer ! null) {let prevDispatcher;if (__DEV__) {prevDispatcher ReactCurrentDispatcher.current; // 暂存dispatcherReactCurrentDispatcher.current InvalidNestedHooksDispatcherOnUpdateInDEV;}try {const currentState: S (queue.lastRenderedState: any);// 计算下次stateconst eagerState lastRenderedReducer(currentState, action);// 在update对象中存储预计算的完整状态和reducer如果在进入render阶段前reducer没有变化那么可以服用eagerState而不用重新再次调用reducerupdate.eagerReducer lastRenderedReducer;update.eagerState eagerState;if (is(eagerState, currentState)) {// 在后续的时间中如果这个组件因别的原因被重渲染且在那时reducer更变后仍有可能重建这次更新return;}} catch (error) {// Suppress the error. It will throw again in the render phase.} finally {if (__DEV__) {ReactCurrentDispatcher.current prevDispatcher;}}}}scheduleWork(fiber, expirationTime);} }useState更新时流程 updateReducer 因为useState底层是useReducer所以在更新时的流程(即重渲染组件后)是调用updateReducer的。 function updateStateS(initialState: (() S) | S, ): [S, DispatchBasicStateActionS] {return updateReducer(basicStateReducer, (initialState: any)); }所以其reducer十分简单 function basicStateReducerS(state: S, action: BasicStateActionS): S {return typeof action function ? action(state) : action; }我们先把复杂情况抛开跑通updateReducer流程 function updateReducer(reducer: (S, A) S,initialArg: I,init?: I S, ){// 获取当前hook,queueconst hook updateWorkInProgressHook();const queue hook.queue;queue.lastRenderedReducer reducer;// action队列的最后一个更新const last queue.last;// 最后一个更新是基本状态const baseUpdate hook.baseUpdate;const baseState hook.baseState;// 找到第一个没处理的更新let first;if (baseUpdate ! null) {if (last ! null) {// 第一次更新时队列是一个自圆queue.last.next queue.first。当第一次update提交后baseUpdate不再为空即可跳出队列last.next null;}first baseUpdate.next;} else {first last ! null ? last.next : null;}if (first ! null) {let newState baseState;let newBaseState null;let newBaseUpdate null;let prevUpdate baseUpdate;let update first;let didSkip false;do {const updateExpirationTime update.expirationTime;if (updateExpirationTime renderExpirationTime) {// 优先级不足跳过这次更新如果这是第一次跳过更新上一个update/state是newBaseupdate/stateif (!didSkip) {didSkip true;newBaseUpdate prevUpdate;newBaseState newState;}// 更新优先级if (updateExpirationTime remainingExpirationTime) {remainingExpirationTime updateExpirationTime;}} else {// 处理更新if (update.eagerReducer reducer) {// 如果更新被提前处理了且reducer跟当前reducer匹配可以复用eagerStatenewState ((update.eagerState: any): S);} else {// 循环调用reducerconst action update.action;newState reducer(newState, action);}}prevUpdate update;update update.next;} while (update ! null update ! first);if (!didSkip) {newBaseUpdate prevUpdate;newBaseState newState;}// 只有在前后state变了才会标记if (!is(newState, hook.memoizedState)) {markWorkInProgressReceivedUpdate();}hook.memoizedState newState;hook.baseUpdate newBaseUpdate;hook.baseState newBaseState;queue.lastRenderedState newState;}const dispatch: DispatchA (queue.dispatch: any);return [hook.memoizedState, dispatch]; }export function markWorkInProgressReceivedUpdate() {didReceiveUpdate true; }后记 作为系列的第一篇文章我选择了最常用的hooks开始抛开提前计算及与react-reconciler的互动整个流程是十分清晰易懂的。mount的时候构建钩子触发dispatch时按序插入update。updateState的时候再按序触发reducer。可以说就是一个简单的redux。
http://www.hkea.cn/news/14385445/

相关文章:

  • 网站开发法律可行性单位建设网站需要招标
  • 闽清建设局网站孵化器网站建设
  • 网站建设需要什么岗位网站如何做映射
  • php源码网站建设教程微信朋友圈投放广告
  • 公司网站建设一般多少钱河南省汝州市文明建设门户网站
  • 人才网站运营建设 材料wordpress 全站404
  • 长垣高端建站南京做网站优化的企业
  • 济南市章丘区建设局网站青岛工商注册核名查询系统
  • 新竹网站wordpress 维基
  • 长春 网站建设做网站产生的流量费怎么算
  • 网站建设预算知乎软件app开发公司
  • 知名的网站开发公司亚马逊网站建设案例分析
  • 有免费网站推荐吗wordpress顶部添加图片
  • 安徽网站开发哪家好dw网页设计代码模板源代码
  • 甘肃网站设计公司学校网站建设方案图片
  • 大连旅游网站建设开网店一个月能赚多少钱
  • 申请免费网站空间世界排行榜前十名
  • 做网站需要哪些流程个人建站网站
  • 旅游电子商务网站策划书wordpress 免费 模板
  • 网站建设排名优化公司哪家好北京公交yy优化
  • 网站建设总体流程做爰视频网站有吗
  • 给银行做网站做网店好还是网站好
  • 网站后台添加新闻百度网站地图
  • 成都o2o网站建设网站专业术语中SEO的意思是
  • 网站建设属于服务还是货物用html5做的简单的网站
  • 山西网站建设哪家好网站制作金华公司电话
  • 郑州那个公司做网站好网站建设lnmp
  • 素材网站php程序源码广告设计网站免费
  • 南京哪家网站建设好门户网站的流程
  • 网站怎么做查询系统帝国cms使用教程