ReactÖÐ×îÉñÆæµÄ²¿·ÖιýÓÚÐéÄâDOM£¬ÒÔ¼°Æä¸ßЧµÄDiffËã·¨¡£ÕâÈÃÎÒÃÇ¿ÉÒÔÎÞÐèµ£ÐÄÐÔÄÜÎÊÌâ¶ø¡±ºÁÎ޹˼ɡ±µÄËæÊ±¡°Ë¢Ð¡±Õû¸öÒ³Ãæ£¬ÓÉÐéÄâDOMÀ´È·±£Ö»¶Ô½çÃæÉÏÕæÕý±ä»¯µÄ²¿·Ö½øÐÐʵ¼ÊµÄDOM²Ù×÷¡£ReactÔÚÕâÒ»²¿·ÖÒѾ×öµ½×㹻͸Ã÷£¬ÔÚʵ¼Ê¿ª·¢ÖÐÎÒÃÇ»ù±¾ÎÞÐè¹ØÐÄÐéÄâDOMÊÇÈçºÎÔË×÷µÄ¡£È»¶ø£¬×÷ΪÓÐ̬¶ÈµÄ³ÌÐòÔ±£¬ÎÒÃÇ×ÜÊǶԼ¼Êõ±³ºóµÄÔÀí³äÂú×ÅºÃÆæ¡£Àí½âÆäÔËÐлúÖÆ²»½öÓÐÖúÓÚ¸üºÃµÄÀí½âReact×é¼þµÄÉúÃüÖÜÆÚ£¬¶øÇÒ¶ÔÓÚ½øÒ»²½ÓÅ»¯React³ÌÐòÒ²»áÓкܴó°ïÖú¡£
ʲôÊÇDOM DiffËã·¨
Web½çÃæÓÉDOMÊ÷À´¹¹³É£¬µ±ÆäÖÐijһ²¿·Ö·¢Éú±ä»¯Ê±£¬Æäʵ¾ÍÊǶÔÓ¦µÄij¸öDOM½Úµã·¢ÉúÁ˱仯¡£ÔÚReactÖУ¬¹¹½¨UI½çÃæµÄ˼·ÊÇÓɵ±Ç°×´Ì¬¾ö¶¨½çÃæ¡£Ç°ºóÁ½¸ö״̬¾Í¶ÔÓ¦Á½Ì×½çÃæ£¬È»ºóÓÉReactÀ´±È½ÏÁ½¸ö½çÃæµÄÇø±ð£¬Õâ¾ÍÐèÒª¶ÔDOMÊ÷½øÐÐDiffËã·¨·ÖÎö¡£
¼´¸ø¶¨ÈÎÒâÁ½¿ÃÊ÷£¬ÕÒµ½×îÉÙµÄת»»²½Öè¡£µ«ÊDZê×¼µÄµÄDiffËã·¨¸´ÔÓ¶ÈÐèÒªO(n^3)£¬ÕâÏÔÈ»ÎÞ·¨Âú×ãÐÔÄÜÒªÇó¡£Òª´ïµ½Ã¿´Î½çÃæ¶¼¿ÉÒÔÕûÌåˢнçÃæµÄÄ¿µÄ£¬ÊƱØÐèÒª¶ÔËã·¨½øÐÐÓÅ»¯¡£Õâ¿´ÉÏÈ¥·Ç³£ÓÐÄѶȣ¬È»¶øFacebook¹¤³Ìʦȴ×öµ½ÁË£¬ËûÃǽáºÏWeb½çÃæµÄÌØµã×ö³öÁËÁ½¸ö¼òµ¥µÄ¼ÙÉ裬ʹµÃDiffËã·¨¸´ÔÓ¶ÈÖ±½Ó½µµÍµ½O(n)
Á½¸öÏàͬ×é¼þ²úÉúÀàËÆµÄDOM½á¹¹£¬²»Í¬µÄ×é¼þ²úÉú²»Í¬µÄDOM½á¹¹£»
¶ÔÓÚͬһ²ã´ÎµÄÒ»×é×ӽڵ㣬ËüÃÇ¿ÉÒÔͨ¹ýΨһµÄid½øÐÐÇø·Ö¡£
Ëã·¨ÉϵÄÓÅ»¯ÊÇReactÕû¸ö½çÃæRenderµÄ»ù´¡£¬ÊÂʵҲ֤Ã÷ÕâÁ½¸ö¼ÙÉèÊǺÏÀí¶ø¾«È·µÄ£¬±£Ö¤ÁËÕûÌå½çÃæ¹¹½¨µÄÐÔÄÜ¡£
²»Í¬½ÚµãÀàÐ͵ıȽÏ
ΪÁËÔÚÊ÷Ö®¼ä½øÐбȽϣ¬ÎÒÃÇÊ×ÏÈÒªÄܹ»±È½ÏÁ½¸ö½Úµã£¬ÔÚReactÖм´±È½ÏÁ½¸öÐéÄâDOM½Úµã£¬µ±Á½¸ö½Úµã²»Í¬Ê±£¬Ó¦¸ÃÈçºÎ´¦Àí¡£Õâ·ÖΪÁ½ÖÖÇé¿ö£º£¨1£©½ÚµãÀàÐͲ»Í¬
£¬£¨2£©½ÚµãÀàÐÍÏàͬ£¬µ«ÊÇÊôÐÔ²»Í¬¡£±¾½ÚÏÈ¿´µÚÒ»ÖÖÇé¿ö¡£
µ±ÔÚÊ÷ÖеÄͬһλÖÃǰºóÊä³öÁ˲»Í¬ÀàÐ͵Ľڵ㣬ReactÖ±½Óɾ³ýÇ°ÃæµÄ½Úµã£¬È»ºó´´½¨²¢²åÈëеĽڵ㡣¼ÙÉèÎÒÃÇÔÚÊ÷µÄͬһλÖÃǰºóÁ½´ÎÊä³ö²»Í¬ÀàÐ͵Ľڵ㡣
renderA: <div /> renderB: <span /> => [removeNode <div />], [insertNode <span />] |
µ±Ò»¸ö½Úµã´Ódiv±ä³Éspanʱ£¬¼òµ¥µÄÖ±½Óɾ³ýdiv½Úµã£¬²¢²åÈëÒ»¸öеÄspan½Úµã¡£Õâ·ûºÏÎÒÃǶÔÕæÊµDOM²Ù×÷µÄÀí½â¡£
ÐèҪעÒâµÄÊÇ£¬É¾³ý½ÚµãÒâζ×ų¹µ×Ïú»Ù¸Ã½Úµã£¬¶ø²»ÊÇÔÙºóÐøµÄ±È½ÏÖÐÔÙÈ¥¿´ÊÇ·ñÓÐÁíÍâÒ»¸ö½ÚµãµÈͬÓÚ¸Ãɾ³ýµÄ½Úµã¡£Èç¹û¸Ãɾ³ýµÄ½ÚµãÖ®ÏÂÓÐ×ӽڵ㣬ÄÇôÕâЩ×Ó½ÚµãÒ²»á±»Íêȫɾ³ý£¬ËüÃÇÒ²²»»áÓÃÓÚºóÃæµÄ±È½Ï¡£ÕâÒ²ÊÇËã·¨¸´ÔÓÄܹ»½µµÍµ½O£¨n£©µÄÔÒò¡£
ÉÏÃæÌáµ½µÄÊǶÔÐéÄâDOM½ÚµãµÄ²Ù×÷£¬¶øÍ¬ÑùµÄÂß¼Ò²±»ÓÃÔÚReact×é¼þµÄ±È½Ï£¬ÀýÈ磺
renderA: <Header /> renderB: <Content /> => [removeNode <Header />], [insertNode <Content />] |
µ±ReactÔÚͬһ¸öλÖÃÓöµ½²»Í¬µÄ×é¼þʱ£¬Ò²ÊǼòµ¥µÄÏú»ÙµÚÒ»¸ö×é¼þ£¬¶ø°Ñд´½¨µÄ×é¼þ¼ÓÉÏÈ¥¡£ÕâÕýÊÇÓ¦ÓÃÁ˵ÚÒ»¸ö¼ÙÉ裬²»Í¬µÄ×é¼þÒ»°ã»á²úÉú²»Ò»ÑùµÄDOM½á¹¹£¬ÓëÆäÀË·Ñʱ¼äÈ¥±È½ÏËüÃÇ»ù±¾Éϲ»»áµÈ¼ÛµÄDOM½á¹¹£¬»¹²»ÈçÍêÈ«´´½¨Ò»¸öеÄ×é¼þ¼ÓÉÏÈ¥¡£
ÓÉÕâÒ»React¶Ô²»Í¬ÀàÐ͵ĽڵãµÄ´¦ÀíÂß¼ÎÒÃǺÜÈÝÒ׵õ½ÍÆÂÛ£¬ÄǾÍÊÇReactµÄDOM DiffË㷨ʵ¼ÊÉÏÖ»»á¶ÔÊ÷½øÐÐÖð²ã±È½Ï£¬ÈçÏÂËùÊö¡£
Öð²ã½øÐнڵã±È½Ï
Ìáµ½Ê÷£¬ÏàÐÅ´ó¶àÊýͬѧÁ¢¿ÌÏëµ½µÄÊǶþ²æÊ÷£¬±éÀú£¬×î¶Ì·¾¶µÈ¸´ÔÓµÄÊý¾Ý½á¹¹Ëã·¨¡£¶øÔÚReactÖУ¬Ê÷µÄËã·¨Æäʵ·Ç³£¼òµ¥£¬ÄǾÍÊÇÁ½¿ÃÊ÷Ö»»á¶Ôͬһ²ã´ÎµÄ½Úµã½øÐбȽϡ£ÈçÏÂͼËùʾ£º

ReactÖ»»á¶ÔÏàͬÑÕÉ«·½¿òÄÚµÄDOM½Úµã½øÐбȽϣ¬¼´Í¬Ò»¸ö¸¸½ÚµãϵÄËùÓÐ×ӽڵ㡣µ±·¢ÏÖ½ÚµãÒѾ²»´æÔÚ£¬Ôò¸Ã½Úµã¼°Æä×Ó½Úµã»á±»Íêȫɾ³ýµô£¬²»»áÓÃÓÚ½øÒ»²½µÄ±È½Ï¡£ÕâÑùÖ»ÐèÒª¶ÔÊ÷½øÐÐÒ»´Î±éÀú£¬±ãÄÜÍê³ÉÕû¸öDOMÊ÷µÄ±È½Ï¡£
ÀýÈ磬¿¼ÂÇÓÐÏÂÃæµÄDOM½á¹¹×ª»»£º

A½Úµã±»Õû¸öÒÆ¶¯µ½D½ÚµãÏ£¬Ö±¹ÛµÄ¿¼ÂÇDOM Diff²Ù×÷Ó¦¸ÃÊÇ
A.parent.remove(A); D.append(A); |
µ«ÒòΪReactÖ»»á¼òµ¥µÄ¿¼ÂÇͬ²ã½ÚµãµÄλÖñ任£¬¶ÔÓÚ²»Í¬²ãµÄ½Úµã£¬Ö»Óмòµ¥µÄ´´½¨ºÍɾ³ý¡£µ±¸ù½Úµã·¢ÏÖ×Ó½ÚµãÖÐA²»¼ûÁË£¬¾Í»áÖ±½ÓÏú»ÙA£»¶øµ±D·¢ÏÖ×Ô¼º¶àÁËÒ»¸ö×Ó½ÚµãA£¬Ôò»á´´½¨Ò»¸öеÄA×÷Ϊ×ӽڵ㡣Òò´Ë¶ÔÓÚÕâÖֽṹµÄת±äµÄʵ¼Ê²Ù×÷ÊÇ£º
A.destroy(); A = new A(); A.append(new B()); A.append(new C()); D.append(A); |
¿ÉÒÔ¿´µ½£¬ÒÔAΪ¸ù½ÚµãµÄÊ÷±»Õû¸öÖØÐ´´½¨¡£
ËäÈ»¿´ÉÏÈ¥ÕâÑùµÄËã·¨ÓÐЩ¡°¼òª¡±£¬µ«ÊÇÆä»ùÓÚµÄÊǵÚÒ»¸ö¼ÙÉ裺Á½¸ö²»Í¬×é¼þÒ»°ã²úÉú²»Ò»ÑùµÄDOM½á¹¹¡£¸ù¾ÝReact¹Ù·½²©¿Í£¬ÕâÒ»¼ÙÉèÖÁ½ñΪֹûÓе¼ÖÂÑÏÖØµÄÐÔÄÜÎÊÌâ¡£Õ⵱ȻҲ¸øÎÒÃÇÒ»¸öÌáʾ£¬ÔÚʵÏÖ×Ô¼ºµÄ×é¼þʱ£¬±£³ÖÎȶ¨µÄDOM½á¹¹»áÓÐÖúÓÚÐÔÄܵÄÌáÉý¡£ÀýÈ磬ÎÒÃÇÓÐʱ¿ÉÒÔͨ¹ýCSSÒþ²Ø»òÏÔʾijЩ½Úµã£¬¶ø²»ÊÇÕæµÄÒÆ³ý»òÌí¼ÓDOM½Úµã¡£
ÓÉDOM DiffËã·¨Àí½â×é¼þµÄÉúÃüÖÜÆÚ
ÔÚÉÏһƪÎÄÕÂÖнéÉÜÁËReact×é¼þµÄÉúÃüÖÜÆÚ£¬ÆäÖеÄÿ¸ö½×¶ÎÆäʵ¶¼ÊǺÍDOM DiffË㷨ϢϢÏà¹ØµÄ¡£ÀýÈçÒÔϼ¸¸ö·½·¨£º
constructor: ¹¹Ô캯Êý£¬×é¼þ±»´´½¨Ê±Ö´ÐУ»
componentDidMount: µ±×é¼þÌí¼Óµ½DOMÊ÷Ö®ºóÖ´ÐУ»
componentWillUnmount: µ±×é¼þ´ÓDOMÊ÷ÖÐÒÆ³ýÖ®ºóÖ´ÐУ¬ÔÚReactÖпÉÒÔÈÏΪ×é¼þ±»Ïú»Ù£»
componentDidUpdate: µ±×é¼þ¸üÐÂʱִÐС£
ΪÁËÑÝʾ×é¼þÉúÃüÖÜÆÚºÍDOM DiffËã·¨µÄ¹ØÏµ£¬±ÊÕß´´½¨ÁËÒ»¸öʾÀý£º
https://supnate.github.io/react-dom-diff/index.html
£¬´ó¼Ò¿ÉÒÔÖ±½Ó·ÃÎÊÊÔÓá£Õâʱµ±DOMÊ÷½øÐÐÈçÏÂת±äʱ£¬¼´´Ó¡°shape1¡±×ª±äµ½¡°shape2¡±Ê±¡£ÎÒÃÇÀ´¹Û²ìÕ⼸¸ö·½·¨µÄÖ´ÐÐÇé¿ö£º

ä¯ÀÀÆ÷¿ª·¢¹¤¾ß¿ØÖÆÌ¨Êä³öÈçϽá¹û£º
C will unmount. C is created. B is updated. A is updated. C did mount. D is updated. R is updated. |
¿ÉÒÔ¿´µ½£¬C½ÚµãÊÇÍêÈ«ÖØ½¨ºóÔÙÌí¼Óµ½D½Úµã֮ϣ¬¶ø²»Êǽ«Æä¡°Òƶ¯¡±¹ýÈ¥¡£Èç¹û´ó¼ÒÓÐÐËȤ£¬Ò²¿ÉÒÔforkʾÀý´úÂ룺https://github.com/supnate/react-dom-diff
¡£´Ó¶ø¿ÉÒÔ×Ô¼ºÌí¼ÓÆäËüÊ÷½á¹¹£¬ÊÔÑéËüÃÇÖ®¼äÊÇÈçºÎת»»µÄ¡£
ÏàͬÀàÐͽڵãµÄ±È½Ï
µÚ¶þÖÖ½ÚµãµÄ±È½ÏÊÇÏàͬÀàÐ͵Ľڵ㣬Ëã·¨¾ÍÏà¶Ô¼òµ¥¶øÈÝÒ×Àí½â¡£React»á¶ÔÊôÐÔ½øÐÐÖØÉè´Ó¶øÊµÏÖ½ÚµãµÄת»»¡£ÀýÈ磺
renderA: <div id="before" /> renderB: <div id="after" /> => [replaceAttribute id "after"] |
ÐéÄâDOMµÄstyleÊôÐÔÉÔÓв»Í¬£¬ÆäÖµ²¢²»ÊÇÒ»¸ö¼òµ¥×Ö·û´®¶ø±ØÐëΪһ¸ö¶ÔÏó£¬Òò´Ëת»»¹ý³ÌÈçÏ£º
renderA: <div style={{color: 'red'}} /> renderB: <div style={{fontWeight: 'bold'}} /> => [removeStyle color], [addStyle font-weight 'bold'] |
Áбí½ÚµãµÄ±È½ÏÉÏÃæ½éÉÜÁ˶ÔÓÚ²»ÔÚͬһ²ãµÄ½ÚµãµÄ±È½Ï£¬¼´Ê¹ËüÃÇÍêȫһÑù£¬Ò²»áÏú»Ù²¢ÖØÐ´´½¨¡£ÄÇôµ±ËüÃÇÔÚͬһ²ãʱ£¬ÓÖÊÇÈçºÎ´¦ÀíµÄÄØ£¿Õâ¾ÍÉæ¼°µ½Áбí½ÚµãµÄDiffËã·¨¡£ÏàÐźܶàʹÓÃReactµÄͬѧ´ó¶àÓöµ½¹ýÕâÑùµÄ¾¯¸æ£º

ÕâÊÇReactÔÚÓöµ½ÁбíʱȴÓÖÕÒ²»µ½keyʱÌáʾµÄ¾¯¸æ¡£ËäÈ»ÎÞÊÓÕâÌõ¾¯¸æ´ó²¿·Ö½çÃæÒ²»áÕýÈ·¹¤×÷£¬µ«Õâͨ³£Òâζ×ÅDZÔÚµÄÐÔÄÜÎÊÌâ¡£ÒòΪReact¾õµÃ×Ô¼º¿ÉÄÜÎÞ·¨¸ßЧµÄÈ¥¸üÐÂÕâ¸öÁÐ±í¡£
Áбí½ÚµãµÄ²Ù×÷ͨ³£°üÀ¨Ìí¼Ó¡¢É¾³ýºÍÅÅÐò¡£ÀýÈçÏÂͼ£¬ÎÒÃÇÐèÒªÍùBºÍCÖ±½Ó²åÈë½ÚµãF£¬ÔÚjQueryÖÐÎÒÃÇ¿ÉÄÜ»áÖ±½ÓʹÓÃ$(B).after(F)À´ÊµÏÖ¡£¶øÔÚReactÖУ¬ÎÒÃÇÖ»»á¸æËßReactеĽçÃæÓ¦¸ÃÊÇA-B-F-C-D-E£¬ÓÉDiffËã·¨Íê³É¸üнçÃæ¡£

ÕâʱÈç¹ûÿ¸ö½Úµã¶¼Ã»ÓÐΨһµÄ±êʶ£¬ReactÎÞ·¨Ê¶±ðÿһ¸ö½Úµã£¬ÄÇô¸üйý³Ì»áºÜµÍЧ£¬¼´£¬½«C¸üгÉF£¬D¸üгÉC£¬E¸üгÉD£¬×îºóÔÙ²åÈëÒ»¸öE½Úµã¡£Ð§¹ûÈçÏÂͼËùʾ£º

¿ÉÒÔ¿´µ½£¬React»áÖð¸ö¶Ô½Úµã½øÐиüУ¬×ª»»µ½Ä¿±ê½Úµã¡£¶ø×îºó²åÈëеĽڵãE£¬Éæ¼°µ½µÄDOM²Ù×÷·Ç³£¶à¡£¶øÈç¹û¸øÃ¿¸ö½ÚµãΨһµÄ±êʶ£¨key£©£¬ÄÇôReactÄܹ»ÕÒµ½ÕýÈ·µÄλÖÃÈ¥²åÈëеĽڵ㣬ÈëÏÂͼËùʾ£º

¶ÔÓÚÁбí½Úµã˳ÐòµÄµ÷ÕûÆäʵҲÀàËÆÓÚ²åÈë»òɾ³ý£¬ÏÂÃæ½áºÏʾÀý´úÂëÎÒÃÇ¿´ÏÂÆäת»»µÄ¹ý³Ì¡£ÈÔȻʹÓÃÇ°ÃæÌáµ½µÄʾÀý£ºhttps://supnate.github.io/react-dom-diff/index.html
£¬ÎÒÃǽ«Ê÷µÄÐÎ̬´Óshape5ת»»µ½shape6£º

¼´½«Í¬Ò»²ãµÄ½ÚµãλÖýøÐе÷Õû¡£Èç¹ûδÌṩkey£¬ÄÇôReactÈÏΪBºÍCÖ®ºóµÄ¶ÔӦλÖÃ×é¼þÀàÐͲ»Í¬£¬Òò´ËÍêȫɾ³ýºóÖØ½¨£¬¿ØÖÆÌ¨Êä³öÈçÏ£º
B will unmount. C will unmount. C is created. B is created. C did mount. B did mount. A is updated. R is updated. |
¶øÈç¹ûÌṩÁËkey£¬ÈçÏÂÃæµÄ´úÂ룺
shape5: function() { return ( <Root> <A> <B key="B" /> <C key="C" /> </A> </Root> ); },
shape6: function() {
return (
<Root>
<A>
<C key="C" />
<B key="B" />
</A>
</Root>
);
}, |
ÄÇô¿ØÖÆÌ¨Êä³öÈçÏ£º
C is updated. B is updated. A is updated. R is updated. |
¿ÉÒÔ¿´µ½£¬¶ÔÓÚÁбí½ÚµãÌṩΨһµÄkeyÊôÐÔ¿ÉÒÔ°ïÖúReact¶¨Î»µ½ÕýÈ·µÄ½Úµã½øÐбȽϣ¬´Ó¶ø´ó·ù¼õÉÙDOM²Ù×÷´ÎÊý£¬Ìá¸ßÁËÐÔÄÜ¡£
С½á
±¾ÎÄ·ÖÎöÁËReactµÄDOM DiffËã·¨¾¿¾¹ÊÇÈçºÎ¹¤×÷µÄ£¬Æä¸´ÔÓ¶È¿ØÖÆÔÚÁËO£¨n£©£¬ÕâÈÃÎÒÃÇ¿¼ÂÇUIʱ¿ÉÒÔÍêÈ«»ùÓÚ״̬À´Ã¿´ÎrenderÕû¸ö½çÃæ¶øÎÞÐèµ£ÐÄÐÔÄÜÎÊÌ⣬¼ò»¯ÁËUI¿ª·¢µÄ¸´ÔÓ¶È¡£¶øËã·¨ÓÅ»¯µÄ»ù´¡ÊÇÎÄÕ¿ªÍ·Ìáµ½µÄÁ½¸ö¼ÙÉ裬ÒÔ¼°ReactµÄUI»ùÓÚ×é¼þÕâÑùµÄÒ»¸ö»úÖÆ¡£Àí½âÐéÄâDOM
DiffËã·¨²»½öÄܹ»°ïÖúÎÒÃÇÀí½â×é¼þµÄÉúÃüÖÜÆÚ£¬¶øÇÒÒ²¶ÔÎÒÃÇʵÏÖ×Ô¶¨Òå×é¼þʱÈçºÎ½øÒ»²½ÓÅ»¯ÐÔÄܾßÓÐÖ¸µ¼ÒâÒå¡£
|