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

灵宝网站制作工作室百度贴吧网页版登录入口

灵宝网站制作工作室,百度贴吧网页版登录入口,工程公司注册经营范围,营销组合策略作者#xff1a;苏畅转发链接#xff1a;https://mp.weixin.qq.com/s/YLSD4IojDWTPlov_RQtVAA前言你可能已经看过其它简易的Hooks实现。那么本文和其它实现有什么区别呢#xff1f;本文的实现完全参照React源码的运行流程。学懂本文#xff0c;去看React源码#xff0c;你…作者苏畅转发链接https://mp.weixin.qq.com/s/YLSD4IojDWTPlov_RQtVAA前言你可能已经看过其它简易的Hooks实现。那么本文和其它实现有什么区别呢本文的实现完全参照React源码的运行流程。学懂本文去看React源码你会发现流程基本一致。这是本实现的在线Demo建议对照着代码来看本文。工作原理对于useState Hook考虑如下例子function App() {  const [num, updateNum]  useState(0);  return  updateNum(num  num  1)}{num};}可以将工作分为两部分通过一些途径产生更新更新会造成组件render。组件render时useState返回的num为更新后的结果。其中步骤1的更新可以分为mount和update调用ReactDOM.render会产生mount的更新更新内容为useState的initialValue(即0)。点击p标签触发updateNum会产生一次update的更新更新内容为num num 1。接下来讲解这两个步骤如何实现。更新是什么通过一些途径产生更新更新会造成组件render。首先我们要明确更新是什么。在我们的极简例子中更新就是如下数据结构const update  {  // 更新执行的函数  action,  // 与同一个Hook的其他更新形成链表  next: null}对于App来说点击p标签产生的update的action为num num 1。如果我们改写下App的onClick// 之前return  updateNum(num  num  1)}{num};// 之后return  {  updateNum(num  num  1);  updateNum(num  num  1);  updateNum(num  num  1);}}{num};那么点击p标签会产生三个update。update数据结构这些update是如何组合在一起呢答案是他们会形成环状单向链表。调用updateNum实际调用的是dispatchAction.bind(null, hook.queue)我们先来了解下这个函数function dispatchAction(queue, action) {  // 创建update  const update  {    action,    next: null  }  // 环状单向链表操作  if (queue.pending  null) {    update.next  update;  } else {    update.next  queue.pending.next;    queue.pending.next  update;  }  queue.pending  update;  // 模拟React开始调度更新  schedule();}环状链表操作不太容易理解这里我们详细讲解下。当产生第一个update(我们叫他u0)此时queue.pending null。update.next update;即u0.next u0它会和自己首尾相连形成单向环状链表。然后queue.pending update;即queue.pending u0queue.pending  u0 --- u0                ^ |                | |                ---------当产生第二个update(我们叫它u1)update.next queue.pending.next;此时queue.pending.next u0 即u1.next u0。queue.pending.next update;即u0.next u1。然后queue.pending update;即queue.pending u1queue.pending  u1 --- u0                ^ |                | |                ---------你可以照着这个例子模拟插入多个update的情况会发现queue.pending始终指向最后一个插入的update。这样做的好处是当我们要遍历update时queue.pending.next指向第一个插入的update。状态如何保存现在我们知道更新产生的update对象会保存在queue中。不同于ClassComponent的实例可以存储数据对于FunctionComponentqueue存储在哪里呢答案是FunctionComponent对应的fiber中。fiber为React16中组件对应的虚拟DOM我们使用如下精简的fiber结构// App组件对应的fiber对象const fiber  {  // 保存该FunctionComponent对应的Hooks链表  memoizedState: null,  // 指向App函数  stateNode: App};Hook数据结构接下来我们关注fiber.memoizedState中保存的Hook的数据结构。可以看到Hook与update类似都通过链表连接。不过Hook是无环的单向链表。hook  {  // 保存update的queue即上文介绍的queue  queue: {    pending: null  },  // 保存hook对应的state  memoizedState: initialState,  // 与下一个Hook连接形成单向无环链表  next: null}注意区分update与hook的所属关系每个useState对应一个hook对象。调用const [num, updateNum] useState(0);时updateNum(即上文介绍的dispatchAction)产生的update保存在useState对应的hook.queue中。模拟React调度更新流程在上文dispatchAction末尾我们通过schedule方法模拟React调度更新流程。function dispatchAction(queue, action) {  // ...创建update  // ...环状单向链表操作  // 模拟React开始调度更新  schedule();}现在我们来实现他。我们用isMount变量指代是mount还是update。// 首次render时是mountisMount  true;function schedule() {  // 更新前将workInProgressHook重置为fiber保存的第一个Hook  workInProgressHook  fiber.memoizedState;  // 触发组件render  fiber.stateNode();  // 组件首次render为mount以后再触发的更新为update  isMount  false;}通过workInProgressHook变量指向当前正在工作的hook。workInProgressHook  fiber.memoizedState;在组件render时每当遇到下一个useState我们移动workInProgressHook的指针。workInProgressHook  workInProgressHook.next;这样只要每次组件render时useState的调用顺序及数量保持一致那么始终可以通过workInProgressHook找到当前useState对应的hook对象。到此为止我们已经完成第一步。通过一些途径产生更新更新会造成组件render。接下来实现第二步。组件render时useState返回的num为更新后的结果。计算state组件render时会调用useState它的大体逻辑如下function useState(initialState) {  // 当前useState使用的hook会被赋值该该变量  let hook;  if (isMount) {    // ...mount时需要生成hook对象  } else {    // ...update时从workInProgressHook中取出该useState对应的hook  }  let baseState  hook.memoizedState;  if (hook.queue.pending) {    // ...根据queue.pending中保存的update更新state  }  hook.memoizedState  baseState;  return [baseState, dispatchAction.bind(null, hook.queue)];}我们首先关注如何获取hook对象if (isMount) {  // mount时为该useState生成hook  hook  {    queue: {      pending: null    },    memoizedState: initialState,    next: null  }  // 将hook插入fiber.memoizedState链表末尾  if (!fiber.memoizedState) {    fiber.memoizedState  hook;  } else {    workInProgressHook.next  hook;  }  // 移动workInProgressHook指针  workInProgressHook  hook;} else {  // update时找到对应hook  hook  workInProgressHook;  // 移动workInProgressHook指针  workInProgressHook  workInProgressHook.next;}当找到该useState对应的hook后如果该hook.queue.pending不为空(即存在update)则更新其state。// update执行前的初始statelet baseState  hook.memoizedState;if (hook.queue.pending) {  // 获取update环状单向链表中第一个update  let firstUpdate  hook.queue.pending.next;  do {    // 执行update action    const action  firstUpdate.action;    baseState  action(baseState);    firstUpdate  firstUpdate.next;    // 最后一个update执行完后跳出循环  } while (firstUpdate ! hook.queue.pending)  // 清空queue.pending  hook.queue.pending  null;}// 将update action执行完后的state作为memoizedStatehook.memoizedState  baseState;完整代码如下function useState(initialState) {  let hook;  if (isMount) {    hook  {      queue: {        pending: null      },      memoizedState: initialState,      next: null    }    if (!fiber.memoizedState) {      fiber.memoizedState  hook;    } else {      workInProgressHook.next  hook;    }    workInProgressHook  hook;  } else {    hook  workInProgressHook;    workInProgressHook  workInProgressHook.next;  }  let baseState  hook.memoizedState;  if (hook.queue.pending) {    let firstUpdate  hook.queue.pending.next;    do {      const action  firstUpdate.action;      baseState  action(baseState);      firstUpdate  firstUpdate.next;    } while (firstUpdate ! hook.queue.pending)    hook.queue.pending  null;  }  hook.memoizedState  baseState;  return [baseState, dispatchAction.bind(null, hook.queue)];}对触发事件进行抽象最后让我们抽象一下React的事件触发方式。通过调用App返回的click方法模拟组件click的行为。function App() {  const [num, updateNum]  useState(0);  console.log(${isMount ? mount : update} num: , num);  return {    click() {      updateNum(num  num  1);    }  }}在线Demo至此我们完成了一个不到100行代码的Hooks。重要的是它与React的运行逻辑相同。在线Demo在Demo中调用window.app.click()模拟组件点击事件。你也可以使用多个useState。function App() {  const [num, updateNum]  useState(0);  const [num1, updateNum1]  useState(100);  console.log(${isMount ? mount : update} num: , num);  console.log(${isMount ? mount : update} num1: , num1);  return {    click() {      updateNum(num  num  1);    },    focus() {      updateNum1(num  num  3);    }  }}与React的区别我们用尽可能少的代码模拟了Hooks的运行但是相比React Hooks他还有很多不足。以下是他与React Hooks的区别React Hooks没有使用isMount变量而是在不同时机使用不同的dispatcher。换言之mount时的useState与update时的useState不是同一个函数。React Hooks有中途跳过更新的优化手段。React Hooks有batchedUpdates当在click中触发三次updateNum精简React会触发三次更新而React只会触发一次。React Hooks的update有优先级概念可以跳过不高优先的update。作者苏畅转发链接https://mp.weixin.qq.com/s/YLSD4IojDWTPlov_RQtVAA
http://www.zqtcl.cn/news/448301/

相关文章:

  • 微信生活门户网站源码河北建设厅网站初始密码
  • 企业如何做网站推广成都外贸网站建设
  • 网页设计 网站建设 哪个好佛山网站建设推广服务
  • 东莞网站建设技术支持产品推广怎么写
  • 银川app购物网站制作公司网站建设怎样提升形象与品牌价值
  • 中山城市建设集团网站信誉好的邯郸网站建设
  • 做网站很赚钱吗贵阳网站建设费用
  • 设计网站的关键点用ps做招生网站
  • 制作网站公司服务器租赁一年的费用网页动画是如何制作出来的
  • 佛山网站优化有莱芜房产网新房
  • 西安英文旅游网站建设中国建筑工程门户商城
  • 山东企业建站软件购物网站是多少
  • 外链收录网站语音识别程序代做网站
  • 天津平台网站建设公司wordpress删除页头页尾
  • 网站加入站长统计wordpress设置手机浏览器
  • 服务器网站备案怎么做网站流量竞品分析
  • 四川省建设工程信息网站上海金融网站制作公
  • php7.2 wordpress黑帽seo软件
  • 网站后台cms做网站项目团队口号
  • 云南哪几个建网站公司九江做网站哪家好
  • 时尚网站模板代码网站模板炫酷
  • 股票网站怎么做动态表格live2d看板娘wordpress
  • 班级网站建设开题报告企业创新平台建设
  • 网站建设有什么要求建设电子商务网站的步骤
  • 百度推广和哪些网站有合作专业网站开发多少钱
  • 相城区住房建设局网站做网站开发电脑配置
  • 成都网站建设制作photoshop网页制作视频教程
  • 深圳网站做的好的公司广州外贸营销网站建设公司
  • 网站你懂我意思正能量晚上不用下载直接进入微信公众号免费模板素材网站
  • 网站设计模板之家南宁seo外包平台