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

衡阳网站排名优化公司网球新闻最新消息

衡阳网站排名优化公司,网球新闻最新消息,一家专门做原产地的网站,建筑工程网求职hello#xff0c;这里是潇晨#xff0c;今天就带着大家一起来手写一个迷你版的hooks#xff0c;方便大家理解hook在源码中的运行机制#xff0c;配有图解#xff0c;保姆级的教程#xff0c;只求同学一个小小的#x1f44d;#xff0c;#x1f436;。 第一步#xf…hello这里是潇晨今天就带着大家一起来手写一个迷你版的hooks方便大家理解hook在源码中的运行机制配有图解保姆级的教程只求同学一个小小的。 第一步引入React和ReactDOM 因为我们要将jsx转变为virtual-dom这一步分工作就交给babel吧而jsx被babel进行词法解析之后会形成React.createElement()的调用而React.createElement()执行之后的返回结果就是jsx对象或者叫virtual-dom。 又因为我们要将我们的demo渲染到dom上所以我们引入ReactDOM。 import React from react; import ReactDOM from react-dom;第二步我们来写一个小demo 我们定义两个状态count和age在点击的时候触发更新让它们的值加1。 在源码中useState是保存在一个Dispatcher对象上面的并且在mount和update的时候取到的是不同的hooks所以我们先暂时从Dispatcher上拿到useState等下在来定义Dispatcher。 接下来定义一个schedule函数每次调用的时候会重新渲染组件。 function App() {let [count, setCount] Dispatcher.useState(1);let [age, setAge] Dispatcher.useState(10);return (pClicked {count} times/pbutton onClick{() setCount(() count 1)} Add count/buttonpAge is {age}/pbutton onClick{() setAge(() age 1)} Add age/button/); }function schedule() { //每次调用会重新渲染组件ReactDOM.render(App /, document.querySelector(#root)); }schedule();第三步定义Dispatcher 在看这部分前先来捋清楚fiber、hook、update的关系看图 Dispatcher是什么Dispatcher在源码中就是一个对象上面存放着各种各样的hooks在mount和update的时候会使用过不同的Dispatcher来看看在源码中Dispatcher是什么样子 在调用useState之后会调用一个resolveDispatcher的函数这个函数调用之后会返回一个dispatcher对象这个对象上就有useState等钩子。 那我们来看看这个函数做了啥事情这个函数比较简单直接从ReactCurrentDispatcher对象上拿到current然后返回出来的这个current就是dispatcher那这个ReactCurrentDispatcher又是个啥别急继续在源码中来找一下。 在源码中有这样一段代码如果是在正式环境中分为两种情况 如果满足 current null || current.memoizedState null说明我们处于首次渲染的时候也就是mount的时候其中current就是我们fiber节点memoizedState保存了fiber上hook也就是说在应用首次渲染的时候current fiber是不存在的我们还没有创造出任何fiber节点或者存在某些fiber但是上面没有构建相应的hook这个时候就可以认为是处于首次渲染的时候我们取到的是HooksDispatcherOnMount如果不满足 current null || current.memoizedState null就说明我们处于更新阶段也就是update的时候我们取到的是HooksDispatcherOnUpdate if (__DEV__) {if (current ! null current.memoizedState ! null) {ReactCurrentDispatcher.current HooksDispatcherOnUpdateInDEV;} else if (hookTypesDev ! null) {ReactCurrentDispatcher.current HooksDispatcherOnMountWithHookTypesInDEV;} else {ReactCurrentDispatcher.current HooksDispatcherOnMountInDEV;}} else {ReactCurrentDispatcher.current current null || current.memoizedState null? HooksDispatcherOnMount: HooksDispatcherOnUpdate;}那我们就来看一下这个HooksDispatcherOnMount和HooksDispatcherOnUpdate是个什么好家伙原来你包含了所有的hooks啊。 const HooksDispatcherOnMount: Dispatcher {readContext,useCallback: mountCallback,useContext: readContext,useEffect: mountEffect,useImperativeHandle: mountImperativeHandle,useLayoutEffect: mountLayoutEffect,useMemo: mountMemo,useReducer: mountReducer,useRef: mountRef,useState: mountState,useDebugValue: mountDebugValue,useDeferredValue: mountDeferredValue,useTransition: mountTransition,useMutableSource: mountMutableSource,useOpaqueIdentifier: mountOpaqueIdentifier,unstable_isNewReconciler: enableNewReconciler, };const HooksDispatcherOnUpdate: Dispatcher {readContext,useCallback: updateCallback,useContext: readContext,useEffect: updateEffect,useImperativeHandle: updateImperativeHandle,useLayoutEffect: updateLayoutEffect,useMemo: updateMemo,useReducer: updateReducer,useRef: updateRef,useState: updateState,useDebugValue: updateDebugValue,useDeferredValue: updateDeferredValue,useTransition: updateTransition,useMutableSource: updateMutableSource,useOpaqueIdentifier: updateOpaqueIdentifier,unstable_isNewReconciler: enableNewReconciler, };所以dispatcher就是个对象里面包含了所有的hooks在首次渲染和更新的时候拿到的是不同的dispatcher在调用hooks的时候就会调用到不同的函数比如如果使用了useState在mount的时候调用到的就是mountState在update的时候调用到的就是updateState。 现在我们来手写一下dispatcherdispatcher是个对象对象上存在useState我们用一个自执行函数来表示此外还需要用到两个变量和一个常量fiber workInProgressHook表示遍历到的hook因为hook会保存在链表上需要遍历链表计算hook上保存的状态为了简单起见定义一个isMounttrue表示mount的时候在update的时候将它设置成false为简单起见fiber就定义成一个对象memoizedState表示这个fiber节点上存放的hook链表stateNode就是第二步的demo。 相关参考视频讲解进入学习 let workInProgressHook;//当前工作中的hook let isMount true;//是否时mount时const fiber {//fiber节点memoizedState: null,//hook链表stateNode: App };const Dispatcher (() {//Dispatcher对象function useState(){//。。。}return {useState}; })();在定义useState之前首先来看看hook和update的数据结构 hook queue上面有pending属性pending也是一条环状链表上面存放了未被更新的update也就是说这些update会以next指针连接成环状链表。memoizedState表示当前的状态next指向下一个hook形成一条链表 const hook {//构建hookqueue: {pending: null//未执行的update链表},memoizedState: null,//当前statenext: null//下一个hook};update action是出发更新的函数next连接下一个update形成一条环状链表 const update {//构建updateaction,next: null};那接下来定义useState吧分三个部分 创建hook或取到hook 在mount的时候调用mountWorkInProgressHook创建一个初始的hook赋值useState传进来的初始值initialState在update的时候调用updateWorkInProgressHook拿到当前正在工作的hook 计算hook上未更新的状态遍历hook上的pending链表调用链表节点上的action函数生成一个新的状态然后更新hook上的状态。返回新的状态和dispatchAction传入queue参数 function useState(initialState) {//第1步创建hook或取到hooklet hook;if (isMount) {hook mountWorkInProgressHook();hook.memoizedState initialState;//初始状态} else {hook updateWorkInProgressHook();}//第2步计算hook上未更新的状态let baseState hook.memoizedState;//初始状态if (hook.queue.pending) {let firstUpdate hook.queue.pending.next;//第一个updatedo {const action firstUpdate.action;baseState action(baseState);//调用action计算新的状态firstUpdate firstUpdate.next;//通过update的action计算state} while (firstUpdate ! hook.queue.pending);//当链表还没遍历完时 进行循环hook.queue.pending null;//重置update链表}hook.memoizedState baseState;//赋值新的state//第3步返回新的状态和dispatchAction传入queue参数return [baseState, dispatchAction.bind(null, hook.queue)];//useState的返回}接下来定义mountWorkInProgressHook和updateWorkInProgressHook这两个函数 mountWorkInProgressHook在mount的时候调用新创建一个hook对象 如果当前fiber不存在memoizedState那当前hook就是这个fiber上的第一个hook将hook赋值给fiber.memoizedState如果当前fiber存在memoizedState那将当前hook接在workInProgressHook.next后面。将当前hook赋值给workInProgressHook updateWorkInProgressHook在update的时候调用返回当前的hook也就是workInProgressHook并且将workInProgressHook指向hook链表的下一个。 function mountWorkInProgressHook() {//mount时调用const hook {//构建hookqueue: {pending: null//未执行的update链表},memoizedState: null,//当前statenext: null//下一个hook};if (!fiber.memoizedState) {fiber.memoizedState hook;//第一个hook的话直接赋值给fiber.memoizedState} else {workInProgressHook.next hook;//不是第一个的话就加在上一个hook的后面形成链表}workInProgressHook hook;//记录当前工作的hookreturn workInProgressHook;}function updateWorkInProgressHook() {//update时调用let curHook workInProgressHook;workInProgressHook workInProgressHook.next;//下一个hookreturn curHook; }第四步定义dispatchAction 创建update挂载载queue.pending上 如果之前queue.pending不存在那创建的这个update就是第一个则update.next update如果之前queue.pending存在则将创建的这个update加入queue.pending的环状链表中 让isMountfalse并且赋值workInProgressHook调用schedule进行更新渲染 function dispatchAction(queue, action) {//触发更新const update {//构建updateaction,next: null};if (queue.pending null) {update.next update;//update的环状链表} else {update.next queue.pending.next;//新的update的next指向前一个updatequeue.pending.next update;//前一个update的next指向新的update}queue.pending update;//更新queue.pendingisMount false;//标志mount结束workInProgressHook fiber.memoizedState;//更新workInProgressHookschedule();//调度更新 }最终代码 import React from react; import ReactDOM from react-dom;let workInProgressHook;//当前工作中的hook let isMount true;//是否时mount时const fiber {//fiber节点memoizedState: null,//hook链表stateNode: App//dom };const Dispatcher (() {//Dispatcher对象function mountWorkInProgressHook() {//mount时调用const hook {//构建hookqueue: {pending: null//未执行的update链表},memoizedState: null,//当前statenext: null//下一个hook};if (!fiber.memoizedState) {fiber.memoizedState hook;//第一个hook的话直接赋值给fiber.memoizedState} else {workInProgressHook.next hook;//不是第一个的话就加在上一个hook的后面形成链表}workInProgressHook hook;//记录当前工作的hookreturn workInProgressHook;}function updateWorkInProgressHook() {//update时调用let curHook workInProgressHook;workInProgressHook workInProgressHook.next;//下一个hookreturn curHook;}function useState(initialState) {let hook;if (isMount) {hook mountWorkInProgressHook();hook.memoizedState initialState;//初始状态} else {hook updateWorkInProgressHook();}let baseState hook.memoizedState;//初始状态if (hook.queue.pending) {let firstUpdate hook.queue.pending.next;//第一个updatedo {const action firstUpdate.action;baseState action(baseState);firstUpdate firstUpdate.next;//循环update链表} while (firstUpdate ! hook.queue.pending);//通过update的action计算statehook.queue.pending null;//重置update链表}hook.memoizedState baseState;//赋值新的statereturn [baseState, dispatchAction.bind(null, hook.queue)];//useState的返回}return {useState}; })();function dispatchAction(queue, action) {//触发更新const update {//构建updateaction,next: null};if (queue.pending null) {update.next update;//update的环状链表} else {update.next queue.pending.next;//新的update的next指向前一个updatequeue.pending.next update;//前一个update的next指向新的update}queue.pending update;//更新queue.pendingisMount false;//标志mount结束workInProgressHook fiber.memoizedState;//更新workInProgressHookschedule();//调度更新 }function App() {let [count, setCount] Dispatcher.useState(1);let [age, setAge] Dispatcher.useState(10);return (pClicked {count} times/pbutton onClick{() setCount(() count 1)} Add count/buttonpAge is {age}/pbutton onClick{() setAge(() age 1)} Add age/button/); }function schedule() {ReactDOM.render(App /, document.querySelector(#root)); }schedule();预览效果https://codesandbox.io/s/custom-hook-tyf19?file/src/index.js
http://www.w-s-a.com/news/191342/

相关文章:

  • expedia电子商务网站建设辽宁网站设计
  • 深圳网站建设网站运营绥芬河市建设局网站
  • 家政服务网站做推广有效果吗做图软件ps下载网站有哪些
  • 北京市建设教育协会网站flash网站制作单选框和复选框ui组件
  • 国外有没有做问卷调查的网站网站网页怎么做
  • 简单个人网站模板下载网站建设整体情况介绍
  • 网站建设做到哪些内容荆门网站建设电话咨询
  • 玉树网站建设公司双11主机 wordpress 2015
  • dw做网站背景图片设置汕头seo管理
  • 个人又什么办法做企业网站唐山哪里建轻轨和地铁
  • 手机网站404页面室内设计公司排名前100
  • 做民宿需要和多家网站合作吗创建软件的步骤
  • 网站导航栏设计要求辽宁省住房和城乡建设厅
  • 海外网站平台腾讯营销平台
  • 东道网站建设良品铺子网络营销案例
  • 免费企业查询软件优化模型
  • 兰亭集势的网站平台建设凡科网站免费版怎么做
  • 在网站做推广要钱吗网站根目录是哪个文件夹
  • 网站建设如何弄链接海外vps一键配置WordPress
  • 1个ip可以做几个网站吗动画制作可以自学吗
  • 顺德建设局网站如何搭建网站
  • 精品网站建设费用 干净磐石网络网页制作简单作业
  • 网站建设需要用软件群晖怎样做网站
  • 网站建设公司有哪博客网站建设方案书
  • 服装商城的网站建设宿迁论坛
  • 网站建设服务市场趋势淮南市网站开发的方式
  • 交互设计包含网站设计wordpress和discuz共存
  • 淮阳城乡建设局网站在线网页翻译软件
  • 什么是电商视觉设计郑州seo服务
  • google网站设计原则青海网站建设与管理