1.vue3ä¸çç¼è¯å¨åçåä¼åçç¥
2.Preact(React)核心原理详解
3.如何看待最近正式发布的源码 Web 全栈框架 Fresh?
4.计算机开发|Github上8个很棒的React项目
5.详解|天猫搜索前端技术历代记
6.preact源码解析,从preact中理解react原理
vue3ä¸çç¼è¯å¨åçåä¼åçç¥
å¦ä¹ ç®æ
ç¼è¯å¨åç
vue3ç¼è¯è¿ç¨åæ
vue3ç¼è¯ä¼åçç¥
å¨åå§åä¹åå¯è½æç¼è¯çè¿ç¨ï¼æç»ç产ç©æ¯ä¸ªæ¸²æå½æ°ï¼æ们ç¥é渲æå½æ°è¿åçå¼æ¯ä¸ä¸ªèæDOM(vnode),分析é£ä¹è¿ä¸ªèæDOMå¨æ们åç»çæ´æ°è¿ç¨ä¸å°åºæä»ä¹ä½ç¨å¢ï¼æ们ä»å¤©å°±æ¥æ¢è®¨ä¸ä¸ã
ç¼è¯å¨åç1.æ¦å¿µå¹¿ä¹ä¸çç¼è¯åçï¼ç¼è¯å¨æ¯å°æºä»£ç 转åææºå¨ç ç软件ï¼æ以ç¼è¯çè¿ç¨åæ¯å°æºä»£ç 转åææºå¨ç çè¿ç¨ï¼ä¹å°±æ¯cpuå¯æ§è¡çäºè¿å¶ä»£ç ãä¾å¦ä½¿ç¨é«çº§è¯è¨javaç¼åçç¨åºéè¦ç¼è¯ææ们çä¸æä½è®¡ç®æºè½çæççåèç ã
å¦æäºè§£è¿ç¼è¯å¨çå·¥ä½æµç¨çåå¦åºè¯¥ç¥éï¼ä¸ä¸ªå®æ´çç¼è¯å¨çå·¥ä½æµç¨ä¼æ¯è¿æ ·ï¼
é¦å ï¼parse解æåå§ä»£ç å符串ï¼çææ½è±¡è¯æ³æ ASTã
å ¶æ¬¡ï¼transform转åæ½è±¡è¯æ³æ ï¼è®©å®åææ´è´´è¿ç®æ ãDSLãçç»æã
æåï¼codegenæ ¹æ®è½¬ååçæ½è±¡è¯æ³æ çæç®æ ãDSLãçå¯æ§è¡ä»£ç ã
2.vueä¸çç¼è¯å¨vueéä¹æç¼è¯çè¿ç¨ï¼æ们ç»å¸¸åçé£ä¸ªHTML模çï¼å¨çæ£å·¥ä½çæ¶åï¼å¹¶ä¸æ¯é£ä¸ªHTML模çï¼å®å®é ä¸æ¯ä¸ä¸ªæ¸²æå½æ°ï¼å¨è¿ä¸ªè¿ç¨ä¸å°±åçäºè½¬æ¢ï¼ä¹å°±æ¯ç¼è¯ï¼ä¹å°±æ¯é£ä¸ªå符串ç模çæç»ä¼åæä¸ä¸ªJSå½æ°ï¼å«renderå½æ°ãæ以å¨è¿ä¸ªè¿ç¨ä¸æ们就éè¦å¼å ¥ç¼è¯å¨çæ¦å¿µãå¨è®¡ç®æºä¸å½ä¸ç§ä¸è¥¿ä»ä¸ç§å½¢æå°å¦ä¸ç§å½¢æè¿è¡è½¬æ¢çæ¶åï¼å°±éè¦ç¼è¯ãç¼è¯å¨ï¼ç¨æ¥å°æ¨¡æ¿å符串ç¼è¯æ为JavaScript渲æå½æ°ç代ç
é£ä¹vueä¸çç¼è¯åçå¨ä»ä¹æ¶åå¢ï¼
è¿ä¸ªæ¶åæ们就éè¦è¿ä¸æ¥äºè§£vueå çä¸åçæ¬çä¸ååè½äºãvueææºå¸¦ç¼è¯å¨åä¸æºå¸¦ç¼è¯çå ï¼å¯¹ä¸åæ建çæ¬ç解éï¼ã
3.è¿è¡æ¶ç¼è¯å¨ä½¿ç¨æºå¸¦ç¼è¯å¨(compiler)çvueå çæ¶åï¼vueç¼è¯çæ¶å»æ¯åçå¨æè½½($mount)çæ¶åã
4.è¿è¡æ¶ä¸ç¼è¯å¦æ使ç¨æªæºå¸¦ç¼è¯å¨çvueå çæ¶åï¼vueå¨è¿è¡æ¶æ¯ä¸ä¼è¿è¡ç¼è¯çãé£ä¹å®çç¼è¯ååçå¨ä»ä¹æ¶åå¢ï¼ä½¿ç¨æªæºå¸¦ç¼è¯å¨çvueå çæ¶åï¼éè¦è¿è¡é¢ç¼è¯ï¼ä¹å°±æ¯åºäºæå»ºå·¥å ·ä½¿ç¨ï¼å°±æ¯æ们平æ¶ä½¿ç¨çvue-cliè¿è¡æ建ç项ç®ï¼å°±æ¯ä½¿ç¨webpackè°ç¨vue-loaderè¿è¡é¢ç¼è¯ï¼å°æævueæ件ï¼å°±æ¯SFCï¼å°éé¢çtemplate模çé¨å转æ¢ærenderå½æ°ãè¿æ ·åç好å¤å°±æ¯vueçå ä½ç§¯åå°äºï¼æ§è¡çæ¶åé度æ´å¿«äºï¼å 为ä¸éè¦è¿è¡ç¼è¯äºã
vueç¼è¯å¨åçç®åæ¥è¯´å°±æ¯ï¼å å°template模ç转æ¢æastæ½è±¡è¯æ³æ ï¼astå转æ¢æ渲æå½æ°renderã
é£ä¹ä»ä¹æ¯æ¯astæ½è±¡è¯æ³æ å¢ï¼
1.astæ½è±¡è¯æ³æ å¨template模çårenderå½æ°ä¹é´æä¸ä¸ªä¸é´äº§ç©å«åastæ½è±¡è¯æ³æ ãå®å°±æ¯ä¸ªjs对象ï¼å®è½å¤æè¿°å½å模ççç»æä¿¡æ¯ï¼è·vnodeå¾ç±»ä¼¼ã注æï¼aståªæ¯ç¨åºè¿è¡è¿ç¨ä¸ç¼è¯äº§ççï¼å®è·æ们æç»ç¨åºçè¿è¡æ¯æ²¡æä»»ä½å ³ç³»çãä¹å°±æ¯å½è¿ä¸ªæ¸²æå½æ°çæä¹åï¼astççå½å¨æå°±ç»æäºï¼ä¸åéè¦äºï¼èé£ä¸ªèæDOMåä¼´éæ´ä¸ªç¨åºççå½å¨æãè¿ä¸ªå°±æ¯aståèæDOMçæ¬è´¨åºå«ã
2.为ä»ä¹éè¦astå¢å¨ast转æ¢ærenderå½æ°çè¿ç¨ä¸ï¼éè¦è¿è¡ç¹å«çæä½ã第ä¸æ¬¡ï¼å°template转æçastæ¯ä¸ªé常ç²ç³çjs对象ï¼æ¯ä¸æ¬¡é常ç²ç³ç转æ¢ï¼ç±»ä¼¼æ£å表达å¼çå¹é ï¼ç¶åæ们çtemplate模çä¸è¿æå¾å¤è¡¨è¾¾å¼ï¼æ令ï¼äºä»¶éè¦éæ°è§£æï¼ç»è¿è¿äºå ·ä½çæ·±å å·¥ç解æ(transform)ä¹åä¼å¾å°ä¸ä¸ªç»æastï¼ç¶åè¿ä¸ªå¯¹è¿ä¸ªç»æastè¿è¡generateï¼çærenderå½æ°
template=>ast=>transform=>ast=>render3.miniçvueç¼è¯å¨ä¸é¢æ们æ¥çä¸ä¸ªminiççvueç¼è¯å¨ï¼å ·ä½ä»£ç å·²çç¥ï¼å ·ä½ä»£ç æå·²ç»æ¾å¨Githubä¸äºï¼mini-vue-compiler
functiontokenizer(input){ ...}functionparse(template){ consttokens=tokenizer(template)...}functiontransform(ast){ ...}functiontraverse(ast,context){ ...}functiongenerate(ast){ ...}functioncompile(template){ //1.解æconstast=parse(template)console.log(JSON.stringify(ast,null,2))//2.转æ¢transform(ast)//3.çæconstcode=generate(ast)console.log(code)//returnfunctionrender(ctx){ //returnh("h3",{ },//ctx.title//)}returnnewFunction(code)()}lettmpl=`<h3>{ { title}}</h3>`compile(tmpl)大æ¦æ以ä¸æä½ï¼å ¶ä¸parseå½æ°å°±æ¯åçå¨ætemplate转æ¢æastçè¿è¿ç¨ï¼å ·ä½æ¯éè¿ä¸äºæ£å表达å¼çå¹é templateä¸çå符串ãæ¯å¦å°
xxx转æast对象ï¼é£ä¹å°±æ¯éè¿æ£å表达å¼å¹é å¦ææ¯
é£ä¹å°±è®¾ç½®ä¸ä¸ªå¼å§æ è®°ï¼åå¾åé¢å¹é å°xxxå 容ï¼ç¶å就设置ä¸ä¸ªåå ç´ ï¼æåå¹é å°é£ä¹å°±è®¾ç½®ä¸ä¸ªç»ææ è®°ï¼ä»¥æ¤ç±»æ¨ãparse解æä¹åå¾å°çæ¯ä¸ä¸ªç²ç³çast对象ãç»è¿parse解æå¾å°ä¸ä¸ªç²ç³çast对象ä¹åï¼å°±ç¨transformè¿è¡æ·±å å·¥ï¼æåè¦ç»è¿generateçæ代ç ã
Vue3ç¼è¯è¿ç¨åææè½½çæ¶åå ætemplateç¼è¯ærenderå½æ°ï¼å¨å建å®ä¾ä¹åï¼ç´æ¥è°ç¨ç»ä»¶å®ä¾çrenderå½æ°å建è¿ä¸ªç»ä»¶ççå®DOMï¼ç¶å继ç»åä¸åéå½ã
1.vue2.xåvue3.xçç¼è¯å¯¹æ¯Vue2.xä¸çCompileè¿ç¨ä¼æ¯è¿æ ·ï¼
parseè¯æ³åæï¼ç¼è¯æ¨¡æ¿çæåå§ç²ç³çASTã
optimizeä¼ååå§ASTï¼æ è®°ASTElement为éææ ¹èç¹æéæèç¹ã
generateæ ¹æ®ä¼ååçASTï¼çæå¯æ§è¡ä»£ç ï¼ä¾å¦_cã_lä¹ç±»çã
å¨Vue3ä¸ï¼æ´ä½çCompileè¿ç¨ä»ç¶æ¯ä¸ä¸ªé¶æ®µï¼ä½æ¯ä¸åäºVue2.xçæ¯ï¼ç¬¬äºä¸ªé¶æ®µæ¢æäºæ£å¸¸ç¼è¯å¨é½ä¼åå¨çé¶æ®µtransformã
parseè¯æ³åæï¼ç¼è¯æ¨¡æ¿çæåå§ç²ç³çASTã
transforméåAST,对æ¯ä¸ä¸ªASTelementè¿è¡è½¬åï¼ä¾å¦ææ¬å ç´ ãæ令å ç´ ãå¨æå ç´ ççç转å
generateæ ¹æ®ä¼ååçASTï¼çæå¯æ§è¡ä»£ç å½æ°ã
2.æºç ç¼è¯å ¥å£æ们å ä»ä¸ä¸ªå ¥å£æ¥å¼å§æ们çæºç é 读ï¼packages/vue/index.tsã
//webå¹³å°ç¹æç¼è¯å½æ°functioncompileToFunction(template:string|HTMLElement,options?:CompilerOptions):RenderFunction{ //çç¥...if(template[0]==='#'){ //è·å模çå 容constel=document.querySelector(template)//çç¥...template=el?el.innerHTML:''}//ç¼è¯const{ code}=compile(template,extend({ //çç¥...},options))constrender=(__GLOBAL__?newFunction(code)():newFunction('Vue',code)(runtimeDom))asRenderFunction//çç¥...return(compileCache[key]=render)}//注åç¼è¯å½æ°registerRuntimeCompiler(compileToFunction)export{ compileToFunctionascompile}è¿ä¸ªå ¥å£æ件ç代ç æ¯è¾ç®åï¼åªæä¸ä¸ªcompileToFunctionå½æ°ï¼ä½å½æ°ä½å çå 容å´åæ¯è¾å ³é®ï¼ä¸»è¦æ¯ç»å以ä¸æ¥éª¤ï¼
ä¾èµæ³¨å ¥ç¼è¯å½æ°è³runtimeregisterRuntimeCompiler(compileToFunction)
runtimeè°ç¨ç¼è¯å½æ°compileToFunction
è°ç¨compileå½æ°
è¿åå å«codeçç¼è¯ç»æ
å°codeä½ä¸ºåæ°ä¼ å ¥Functionçæé å½æ°å°çæçå½æ°èµå¼ç»renderåé
å°renderå½æ°ä½ä¸ºç¼è¯ç»æè¿å
3.templateè·åapp.mount()è·åäºtemplatepackages/runtime-dom/src/index.ts
4.ç¼è¯templatecompileå°ä¼ ?templateç¼è¯ä¸ºrenderå½æ°ï¼packages/runtime-core/src/component.ts
å®é æ§?çæ¯baseCompileï¼packages/compiler-core/src/compile.ts
第?æ¥è§£æ-parseï¼è§£æå符串template为æ½è±¡è¯æ³æ ast
第?æ¥è½¬æ¢-transformï¼è§£æå±æ§ãæ ·å¼ãæ令ç
第ä¸æ¥?æ-generateï¼å°ast转æ¢ä¸ºæ¸²æå½æ°
Vue3ç¼è¯å¨ä¼åçç¥è¿æ¯ä¸ä¸ªéå¸¸å ¸åçç¨å åæ¢æ¶é´çæä½
1.éæèç¹æå<div><div>{ { msg}}</div><p>coboy</p><p>coboy</p><p>coboy</p></div>以ä¸è¿ä¸ªæ®µtemplateå¦æ没æå¼å¯éæèç¹æåå®ç¼è¯åæ¯è¿æ ·çï¼
import{ toDisplayStringas_toDisplayString,createVNodeas_createVNode,openBlockas_openBlock,createBlockas_createBlock}from"vue"exportfunctionrender(_ctx,_cache,$props,$setup,$data,$options){ return(_openBlock(),_createBlock("div",null,[_createVNode("div",null,_toDisplayString(_ctx.msg),1/*TEXT*/),_createVNode("p",null,"coboy"),_createVNode("p",null,"coboy"),_createVNode("p",null,"coboy")]))}å¦æå¼å¯äºéæèç¹æåä¹åå®ç¼è¯ååæ¯è¿æ ·çï¼
import{ toDisplayStringas_toDisplayString,createVNodeas_createVNode,openBlockas_openBlock,createBlockas_createBlock}from"vue"const_hoisted_1=/*#__PURE__*/_createVNode("p",null,"coboy",-1/*HOISTED*/)const_hoisted_2=/*#__PURE__*/_createVNode("p",null,"coboy",-1/*HOISTED*/)const_hoisted_3=/*#__PURE__*/_createVNode("p",null,"coboy",-1/*HOISTED*/)exportfunctionrender(_ctx,_cache,$props,$setup,$data,$options){ return(_openBlock(),_createBlock("div",null,[_createVNode("div",null,_toDisplayString(_ctx.msg),1/*TEXT*/),_hoisted_1,_hoisted_2,_hoisted_3]))}æ们å¯ä»¥çå°templateéåå¨å¤§éçä¸ä¼åçpæ ç¾ï¼æ以å½è¿ä¸ªç»ä»¶éæ°æ¸²æçæ¶åï¼è¿äºéæçä¸ä¼åçæ ç¾å°±ä¸åºè¯¥å次å建äºãæ以vue3å°±æè¿äºéæçä¸ä¼åçæ ç¾çVNodeæ¾å¨äºrenderå½æ°ä½ç¨åçå¤é¢ï¼å¨ä¸æ¬¡renderå½æ°å次æ§è¡çæ¶åï¼é£äºéææ ç¾çVNodeå·²ç»å¨å åéäºï¼ä¸éè¦éæ°å建äºãç¸å½äºå ç¨å½åæºå¨çå åï¼é¿å éå¤å建VNodeï¼ç¨å åæ¥æ¢æ¶é´ã大家ä»ç»æé ä¸çªéææåçåç¼ï¼éæäºåæ们å¯ä»¥ä¸çï¼ä½æ¯æåäºåï¼ç´ææ¬æå°è¡¨è¾¾åºå®ï¼éæèç¹ï¼è¢«æé«äºã
2.è¡¥ä¸æ è®°åå¨æå±æ§è®°å½<div><div:title="title">coboy</div></div>ææå°±æ¯å¨ç¼è¯çè¿ç¨ä¸ï¼å人ç¼ä¸æ ·å¯¹æ¨¡çè¿è¡æ«æçåªäºä¸è¥¿æ¯å¨æçï¼ç¶åæåæè¿äºå¨æçä¸è¥¿æåä¿åèµ·æ¥ï¼ä½ä¸ªæ è®°åè®°å½ï¼çä¸æ¬¡æ´æ°çæ¶åï¼åªæ´æ°è¿äºä¿åèµ·æ¥çå¨æçè®°å½ãæ¯å¦ä¸é¢æ¨¡ççtitleæ¯å¨æçï¼æåå个æ è®°åè®°å½ï¼æ´æ°çæ¶åå°±åªæ´æ°titleé¨åçå 容ã
import{ createVNodeas_createVNode,openBlockas_openBlock,createBlockas_createBlock}from"vue"exportfunctionrender(_ctx,_cache,$props,$setup,$data,$options){ return(_openBlock(),_createBlock("div",null,[_createVNode("div",{ title:_ctx.title},"coboy",8/*PROPS*/,["title"])]))}<div><div:title="title">{ { text}}</div></div>import{ toDisplayStringas_toDisplayString,createVNodeas_createVNode,openBlockas_openBlock,createBlockas_createBlock}from"vue"exportfunctionrender(_ctx,_cache,$props,$setup,$data,$options){ return(_openBlock(),_createBlock("div",null,[_createVNode("div",{ title:_ctx.title},_toDisplayString(_ctx.text),9/*TEXT,PROPS*/,["title"])]))}æ们å¯ä»¥è§å¯å°å¨_createVNodeå½æ°ç第å个åæ°æ¯ä¸ª9ï¼åé¢æ¯ä¸ä¸ªæ³¨éï¼/TEXT,PROPS/ï¼è¿ä¸ªæ¯è¡¨ç¤ºå¨å½åçèç¹éé¢æ两个ä¸è¥¿æ¯å¨æçï¼ä¸ä¸ªæ¯å é¨çææ¬ï¼ä¸ä¸ªæ¯å±æ§ï¼ç¶åå ·ä½æ¯åªä¸ªå±æ§ï¼å¨ç¬¬äºä¸ªåæ°çæ°ç»éé¢åè®°å½äºä¸æ¥["title"]ï¼æ个titleçå±æ§æ¯å¨æçã
å¨å°æ¥è¿è¡patchæ´æ°çæ¶åï¼å°±å¯ä»¥æ ¹æ®å½åè®°å½çä¿¡æ¯ï¼è¿è¡æ´æ°ï¼ç¼©åæ´æ°è¿ç¨åæä½ï¼å¯ä»¥é常精确å°åªè¿è¡titleåææ¬çæ´æ°ã
å¦ædivæ ç¾éæ¯éæææ¬çè¯ï¼_createVNodeå½æ°ç第å个åæ°ååæäº8ï¼åé¢ç注éåæäºï¼/PROPS/ï¼åé¢ç第äºä¸ªåæ°æ°æ®ä¸åã
_createVNodeå½æ°ç第å个åæ°çæ°åå ¶å®æ¯ä¸ä¸ªäºè¿å¶æ°å转æåè¿å¶çæ°åã
8çäºè¿å¶æ¯ï¼9çäºè¿å¶æ¯ï¼å¾å®¹æå¯ä»¥çåºäºè¿å¶çæ¯ä¸ä½çæ°åé½ä»£è¡¨çç¹æ®çå«ä¹ãè¿äºæ°åå°±æ¯patchFlagï¼é£ä¹ä»ä¹æ¯patchFlagå¢ï¼
ä»ä¹æ¯patchFlagpatchFlagæ¯complieræ¶çtransformé¶æ®µè§£æASTElementæä¸çè¡¥ä¸æ è®°ãå®ä¼ä¸ºruntimeæ¶çpatchVNodeæä¾ä¾æ®ï¼ä»èå®ç°é¶åæ´æ°VNodeåéææåçææã
patchFlag被å®ä¹ä¸ºä¸ä¸ªæ°åæ举类åï¼å®çæ¯ä¸ä¸ªæ举å¼å¯¹åºçæ è¯æä¹æ¯ï¼
TEXT=1å¨æææ¬çå ç´
CLASS=2å¨æç»å®classçå ç´
STYLE=4å¨æç»å®styleçå ç´
PROPS=8å¨æpropsçå ç´ ï¼ä¸ä¸å«æclassãstyleç»å®
FULL_PROPS=å¨æpropså带ækeyå¼ç»å®çå ç´
HYDRATE_EVENTS=äºä»¶çå¬çå ç´
STABLE_FRAGMENT=åå ç´ ç订é ä¸ä¼æ¹åçFragmentå ç´
KEYED_FRAGMENT=èªå·±æåå ç´ å¸¦ækeyå¼ç»å®çFragmentå ç´
UNKEYED_FRAGMENT=没ækeyå¼ç»å®çFragmentå ç´
NEED_PATCH=带ærefãæ令çå ç´
DYNAMIC_SLOTS=å¨æslotçç»ä»¶å ç´
HOISTED=-1éæçå ç´
BAIL=-2ä¸æ¯renderå½æ°çæçä¸äºå ç´ ï¼ä¾å¦renderSlot
æ´ä½ä¸patchFlagçå为两大类ï¼
å½patchFlagçå¼å¤§äº0æ¶ï¼ä»£è¡¨æ对åºçå ç´ å¨patchVNodeæ¶ærenderæ¶æ¯å¯ä»¥è¢«ä¼åçæææ´æ°ç
å½patchFlagçå¼å°äº0æ¶ï¼ä»£è¡¨æ对åºçå ç´ å¨patchVNodeæ¶ï¼æ¯éè¦è¢«fulldiffï¼å³è¿è¡éå½éåVNodetreeçæ¯è¾æ´æ°è¿ç¨ã
以ä¸å°±æ¯vue3çä¸ä¸ªé常é«æçä¼åçç¥å«è¡¥ä¸æ è®°åå¨æå±æ§è®°å½ã
3.ç¼åäºä»¶å¤çç¨åºfunctiontokenizer(input){ ...}functionparse(template){ consttokens=tokenizer(template)...}functiontransform(ast){ ...}functiontraverse(ast,context){ ...}functiongenerate(ast){ ...}functioncompile(template){ //1.解æconstast=parse(template)console.log(JSON.stringify(ast,null,2))//2.转æ¢transform(ast)//3.çæconstcode=generate(ast)console.log(code)//returnfunctionrender(ctx){ //returnh("h3",{ },//ctx.title//)}returnnewFunction(code)()}lettmpl=`<h3>{ { title}}</h3>`compile(tmpl)0å°æ¥æ¡æ¶ä¼åreacté£æ ·æ@click="onClick"åæ@click="()=>onClick()"ï¼æåå¯è½æ¯è¿æ ·çä¸ä¸ªç®å¤´å½æ°ãé£å°±æå³çæ¯æ¬¡onClickçå½æ°é½æ¯ä¸ä¸ªå ¨æ°çå½æ°ï¼é£å°±ä¼é æè¿ä¸ªåè°å½æ°ææ没æåï¼é½ä¼è¢«è®¤ä¸ºåäºï¼é£å°±å¿ é¡»è¿è¡ä¸ç³»åçæ´æ°ï¼é£ä¹å¦æè½æè¿ä¸ªåè°å½æ°ç¼åèµ·æ¥ï¼æ´æ°çæ¶åï¼å°±ä¸è¦åå建äºã
æªè¿è¡ç¼åäºä»¶å¤çç¨åºä¹åçç¼è¯
functiontokenizer(input){ ...}functionparse(template){ consttokens=tokenizer(template)...}functiontransform(ast){ ...}functiontraverse(ast,context){ ...}functiongenerate(ast){ ...}functioncompile(template){ //1.解æconstast=parse(template)console.log(JSON.stringify(ast,null,2))//2.转æ¢transform(ast)//3.çæconstcode=generate(ast)console.log(code)//returnfunctionrender(ctx){ //returnh("h3",{ },//ctx.title//)}returnnewFunction(code)()}lettmpl=`<h3>{ { title}}</h3>`compile(tmpl)1è¿è¡ç¼åäºä»¶å¤çç¨åºä¹åçç¼è¯
functiontokenizer(input){ ...}functionparse(template){ consttokens=tokenizer(template)...}functiontransform(ast){ ...}functiontraverse(ast,context){ ...}functiongenerate(ast){ ...}functioncompile(template){ //1.解æconstast=parse(template)console.log(JSON.stringify(ast,null,2))//2.转æ¢transform(ast)//3.çæconstcode=generate(ast)console.log(code)//returnfunctionrender(ctx){ //returnh("h3",{ },//ctx.title//)}returnnewFunction(code)()}lettmpl=`<h3>{ { title}}</h3>`compile(tmpl).åblockè¿æ¯ä»ä¹ææå¢ï¼æ ¹æ®å°¤é¨æºªæ¬äººç解æï¼ä»è¯´ï¼æ ¹æ®ä»çç»è®¡é£ä¸ªå¨æçé¨åæå¤åªæä¸åä¹ä¸ï¼åºæ¬ä¸é½æ¯éæé¨åï¼æ以å¨ç¼è¯çè¿ç¨ä¸ï¼è½ä¸è½åç°é£ä¸ªæ¯è¾å°çå¨æé¨åï¼æå®æ¾å°æ¯è¾é ä¸
Preact(React)核心原理详解
本文作者:字节跳动 - 宝丁
在前端领域,React 是源码一个广为人知的前端开发框架,它革新了全栈 Web 开发的分析体验。React 引入了诸如 JSX、源码虚拟 DOM、分析麻将源码苹果组件化与合成事件等概念。源码然而,分析探究其源码时,源码庞大且晦涩的分析代码体系往往让这一过程变得艰难。为了解答这个挑战,源码本文将聚焦 Preact,分析一个轻量级的源码 React 替代方案,其体积仅为 3KB。分析Preact 的源码设计初衷是提升性能,简化复杂性。我们将从以下几个角度深入探讨 Preact 的核心原理。
一、Preact 是go cms 源码什么?
Preact 是一个功能与 React 类似的轻量级前端框架。它的名字中的“P”意味着“Performance”,强调了提高性能的初衷。Preact 旨在提供 React 的核心功能,同时以更简洁的代码实现。
二、Preact 与 React 的区别
1. 事件系统:React 内置了事件合成系统,主要使用 `onChange` 方法处理表单组件的值更新。相比之下,Preact 直接利用浏览器原生的各种棋盘源码事件系统,使用 `onInput` 方法,因此在体积上更加精简。
2. DOM 规范描述:在描述 DOM 类名时,React 要求使用 `className`。Preact 支持使用 `class` 直接描述 DOM 类名,使其更贴近原生 DOM 规范。
三、Preact 的工作流程
1. JSX:JSX 是 Preact 的模板语法,它允许用类似 HTML 的ros替换源码结构描述 DOM。经过转换,JSX 被编译为函数调用,进而生成原生 DOM 结构。
2. Virtual DOM:Preact 采用 Virtual DOM 技术,将 DOM 更新操作最小化。它通过比较虚拟 DOM 和实际 DOM,仅对发生变化的部分进行更新。
四、Diff 算法详解
1. Diff 儿童节点:比较新旧儿童节点,javavalue注解源码匹配相同的 key,进行差异比较,对未匹配的节点进行处理。
2. Diff 阶段:根据节点类型(Fragment、Component、DOM node)进行不同处理,如更新组件状态、创建新 DOM 节点或更新现有 DOM 节点。
3. Diff 属性:比较新旧 DOM 节点属性,仅更新变化的部分。
五、结合实际组件
通过一个简单的 Clock 组件,直观展示 Preact 的渲染流程,帮助理解 Preact 的工作原理。
六、Preact Hooks
Preact Hooks 是 React Hooks 的替代方案,提供了性能优化的组件状态管理机制。分为三类:MemoHook、ReducerHook 和 EffectHook,分别用于性能优化、状态管理与副作用操作。
七、结束语
本文深入介绍了 Preact 的核心原理,包括框架设计、与 React 的比较、工作流程、Diff 算法、实际应用以及 Hooks 机制。通过 Preact,前端开发者可以更高效地构建应用,同时理解其与 React 的异同。希望本文能够帮助大家更深入地掌握 Preact 的使用方法与性能优化策略。
如何看待最近正式发布的 Web 全栈框架 Fresh?
Fresh 是由 Deno 作者推出的一款 Web 全栈框架,最近正式发布了 1.0 版本并支持了生产环境。它在 Github 上热度较高,适合深入研究。以下从框架定位、上手体验、优劣势评估和源码实现四个方面介绍 Fresh 框架。
Fresh 定位为 Web 全栈框架,与 Next.js 和 Remix 相似,具有 Deno 的优势,内置测试工具和支持 blogs.com/zhaojietec/p/.html
ããä¸è¿éè¦æ³¨æçæ¯ï¼ç®å为æ¢ï¼UIExplorerå¨Androidä¸æä¸ä¸ªbugï¼IOSä¸æ²¡æé®é¢ï¼éè¿googleå¯ä»¥æ¾å°äºè§£å³åæ³ã/facebook/react-native/issues/
ããåå æ¯ï¼js代ç åandroidåç代ç ä¸åæ¥ï¼éè¿build.gradleå¯ä»¥çå°androidä¸çå¼ç¨çreactNativeæ ¸å¿åºä¸ºï¼èjs代ç çæ¬å·²ç»æ´æ°å°äºã
ãã解å³çåæ³æ2个ï¼ä¸ä¸ªæ¯ä½¿ç¨gitå·¥å ·(å¦smartGit)ï¼å°js代ç æ¢å¤å°ä¹åççæ¬ï¼å¦ä¸ä¸ªåæ³æ¯éæ°ç¼è¯reactNativeçæ ¸å¿åºï¼ç¼è¯æ ¸å¿åºéè¦ndkï¼å¨macä¸æ²¡æé®é¢ï¼å¨windowsç¼è¯ä¼åºéãç¼è¯reactNativeæ ¸å¿åºï¼å¯¹UIExplorerä¸æ³¨éæçä¾èµé¡¹è¿è¡ä¿®æ¹å³å¯ï¼ç¼è¯é度è¾æ ¢ éè¦å¨çº¿ä¸è½½ç¬¬ä¸æ¹ä¾èµåºã
ããdependencies {
ããcompile fileTree(dir: 'libs', include: ['*.jar'])
ããcompile 'com.android.support:appcompat-v7:.0.1'
ãã// Depend on pre-built React Native//compile 'com.facebook.react:react-native:0..+'
ãã// Depend on React Native source.
ãã// This is useful for testing your changes when working on React Native.
ããcompile project(':ReactAndroid')
ãã}
ããç±äºwindowsä¸æ æ³ç¼è¯ï¼æ以è¿éæä¾ç¼è¯å¥½çaaræ件ï¼ä¿®æ¹UIExplorer build.gradleä¸çä¾èµé¡¹å°±å¯ä»¥äºãè³äºå¦ä½å¼å ¥aaræ件ï¼å¯ä»¥èªè¡æç´¢ãå½ç¶macä¸åæ ·ä¹å¯ä»¥ç¨è¿ä¸ªaarï¼å¯ä»¥çå»ä¸å°éº»ç¦ã
2024-11-28 22:541494人浏览
2024-11-28 22:442635人浏览
2024-11-28 22:382274人浏览
2024-11-28 22:27544人浏览
2024-11-28 21:492503人浏览
2024-11-28 21:371162人浏览
1.长沙哪里做电商的多2.去培训机构学习编程是否靠谱?坐标长沙,目前犹豫源码时代和动力节点。3.长沙棋牌游戏开发公司源码?4.长沙的源码时代学前端怎么样?5.长沙有哪些公司能做APP,并且做的好的!6
1.WIFI和蓝牙的工作原理是什么?2.[蓝牙系列] WiFi 与蓝牙BT共享信道机制(自适应跳频-AFH)3.Github上实用的嵌入式项目之——基于WiFi和蓝牙的客流计数器4.如何在iOS12中
1.MapBox源码解读 01 - style 的加载逻辑2.Vue3 源码解读 | v-if 和 v-show 指令实现的原理3.技术干货kubectl源码阅读—get命令4.源码级解析,搞懂 Re