±à¼ÍƼö: |
±¾ÎÄ×ÅÖØ½éÉÜÁËPreactµÄ¹¤×÷Á÷³ÌÒÔ¼°ÆäÖи÷¸öÄ£¿éµÄһЩ¹¤×÷ϸ½Ú£¬Ï£Íû¿ÉÒÔ´ïµ½Å×שÒýÓñµÄ×÷Óá£
±¾ÎÄÀ´×ÔÓÚÖªºõ,ÓÉ»ðÁú¹ûÈí¼þAnna±à¼ÍƼö¡£ |
|
ǰһ¶Îʱ¼äÓÉÓÚReact LicenceµÄÎÊÌ⣬ÍŶÓÄÚ²¿»ý¼«µÄ̽Ë÷ReactµÄÌæ´ú·½°¸£¬Í¬Ê±¿¼Âǵ½Ö®ºó¿ÉÄÜ¿ªÕ¹µÄÒÆ¶¯¶ËÒµÎñ£¬ÍŶÓÄ¿±êÊÇÏ£ÍûÄܹ»ÕÒµ½Ò»¸öÇ¨ÒÆ³É±¾µÍ£¬ÌåÁ¿Ð¡µÄÌæ´ú²úÆ·¡£¾¹ý¶à·½Ì½Ë÷£¬Preact½øÈëÁËÎÒÃǵÄÊÓÒ°¡£´Ó½Ó´¥µ½Preact¿ªÊ¼£¬Ò»Â·Ñ§Ï°ÏÂÀ´ÕÛËðÁËÐí¶àÍ··¢£¬Ò²ÊÕ»ñ²»ÉÙ˼¿¼£¬ÕâÀïÏëºÍ´ó¼Ò½éÉÜÒ»ÏÂPreactµÄʵÏÖ˼·£¬Ò²·ÖÏíÒ»ÏÂ×Ô¼ºµÄ˼¿¼ËùµÃ¡£
PreactÊÇʲô
Ò»¾ä»°½éÉÜPreact£¬ËüÊÇReactµÄ3KBÇáÁ¿Ìæ´ú·½°¸£¬ÓµÓÐͬÑùµÄES6 API¡£Èç¹û¾õµÃ¾ÍÕâôһ¾ä»°Ì«Ä£ºýµÄ»°£¬ÎÒ»¹¿ÉÒÔÔÙ†ªà¼¸¾ä¡£Preact
= performance + react£¬ÕâÊÇPreactÃû×ÖµÄÓÉÀ´£¬ÆäÖÐÒ»¸öperformance×ãÒÔ¿ú¼û×÷ÕßµÄÓÃÐÄ¡£ÏÂÃæÕâÕÅͼ·´Ó³ÁËÔÚ³¤Áбí³õʼ»¯µÄ³¡¾°Ï£¬²»Í¬¿ò¼ÜµÄ±íÏÖ£¬¿ÉÒÔ¿´³öPreactȷʵÐÔÄܳöÖÚ¡£
¸ßÐÔÄÜ£¬ÇáÁ¿£¬¼´Ê±Éú²úÊÇPreact¹Ø×¢µÄºËÐÄ¡£»ùÓÚÕâЩÖ÷Ì⣬Preact¹Ø×¢ÓÚReactµÄºËÐŦÄÜ£¬ÊµÏÖÁËÒ»Ì×¼òµ¥¿ÉÔ¤²âµÄdiffË㷨ʹËü³ÉΪ×î¿ìµÄÐéÄâ
DOM ¿ò¼ÜÖ®Ò»£¬Í¬Ê±preact-compatΪ¼æÈÝÐÔÌṩÁ˱£Ö¤£¬Ê¹µÃPreact¿ÉÒÔÎÞ·ì¶Ô½ÓReactÉú̬ÖеĴóÁ¿×é¼þ£¬Í¬Ê±Ò²²¹³äÁ˺ܶàPreactûÓÐʵÏֵŦÄÜ¡£

³¤Áбí³õʼ»¯Ê±¼ä¶Ô±È
PreactµÄ¹¤×÷Á÷³Ì
¼òµ¥½éÉÜÁËPreactµÄǰÉú½ñÊÀÒԺ󣬽ÓÏÂÀ´ËµÏÂPreactµÄ¹¤×÷Á÷³Ì£¬Ö÷Òª°üº¬Îå¸öÄ£¿é£º
component
hº¯Êý
render
diffËã·¨
»ØÊÕ»úÖÆ
Á÷ת¹ý³Ì¼ûÏÂͼ¡£
Ê×ÏÈÊÇÎÒÃǶ¨ÒåºÃµÄ×é¼þ£¬ÔÚäÖȾ¿ªÊ¼µÄʱºò£¬Ê×ÏÈ»á½øÈëhº¯ÊýÉú³É¶ÔÓ¦µÄvirtual node£¨Èç¹ûÊÇJSX±àд£¬Ö®Ç°»¹ÐèÒªÒ»²½×ªÂ룩¡£Ã¿Ò»¸övnodeÖаüº¬×ÔÉí½ÚµãµÄÐÅÏ¢£¬ÒÔ¼°×Ó½ÚµãµÄÐÅÏ¢£¬Óɴ˶øÁ¬½á³ÉΪһ¿Ãvirtual
domÊ÷¡£»ùÓÚÉú³ÉµÄvnode£¬renderÄ£¿é»á½áºÏµ±Ç°domÊ÷µÄÇé¿ö½øÐÐÁ÷³Ì¿ØÖÆ£¬²¢ÎªºóÐøµÄdiff²Ù×÷×öһЩ׼±¸¹¤×÷¡£PreactµÄdiffË㷨ʵÏÖÓбðÓÚreact»ùÓÚË«virtual
domÊ÷µÄ˼·£¬Preactֻά³ÖÒ»¿ÃеÄvirtual domÊ÷£¬diff¹ý³ÌÖлá»ùÓÚdomÊ÷»¹Ô³ö¾ÉµÄvirtual
domÊ÷£¬ÔÙ½«Á½Õß½øÐбȽϣ¬²¢ÔڱȽϹý³ÌÖÐʵʱ¶ÔdomÊ÷½øÐÐpatch²Ù×÷£¬×îÖÕÉú³ÉеÄdomÊ÷¡£Óë´Ëͬʱ£¬diff¹ý³ÌÖб»Ð¶ÔصÄ×é¼þºÍ½Úµã²»»á±»Ö±½Óɾ³ý£¬¶øÊDZ»·Ö±ð·ÅÈë»ØÊÕ³ØÖлº´æ£¬µ±ÔÙ´ÎÓÐͬÀàÐ͵Ä×é¼þ»ò½Úµã±»¹¹½¨Ê±£¬¿ÉÒÔÔÚ»ØÊÕ³ØÖÐÕÒµ½Í¬ÃûÔªËØ½øÐиÄÔ죬±ÜÃâ´ÓÁã¹¹½¨µÄ¿ªÏú¡£

Preact¹¤×÷Á÷³Ìͼ
ÔÚÁ˽âÁËPreactµÄ¹¤×÷Á÷³ÌÖ®ºó£¬½ÓÏÂÀ´»á¶ÔÉÏÎÄÌáµ½µÄÎå¸öÄ£¿éÒ»Ò»½â¶Á¡£
1. Component
¹Ø¼ü´Ê£ºhook£¬linkState, ÅúÁ¿¸üÐÂ
ÏàÐÅÓйýreact¿ª·¢¾ÑéµÄͬѧ¶ÔcomponentµÄ¸ÅÄî¶¼²»»áİÉú£¬ÕâÀïÒ²²»×ö¹ý¶à½âÊÍ£¬Ö»ÊǽéÉÜһЩPreactÔÚcomponent²ãÃæÉϵÄÌí¼ÓµÄÐÂÌØÐÔ¡£
hookº¯Êý
³ýÁË»ù±¾µÄÉúÃüÖÜÆÚº¯ÊýÍ⣬Preact»¹ÌṩÈý¸öhookº¯Êý£¬·½±ãÓû§ÔÚÖ¸¶¨µÄʱ¼äµãÖ´ÐÐͳһ²Ù×÷¡£
afterMount
afterUpdate
beforeUnmount
linkState
linkStateÕë¶ÔµÄ³¡¾°ÊÇÔÚrender·½·¨ÖÐΪÓû§²Ù×÷µÄ»Øµ÷°ó¶¨this£¬ÕâÑùÿ´ÎäÖȾ¶¼ÔÚ¾Ö²¿´´½¨Ò»¸öº¯Êý±Õ°ü£¬ÕâÑùЧÂÊÊ®·ÖµÍ϶øÇÒ»áÆÈʹÀ¬»ø»ØÊÕÆ÷×öÐí¶à²»±ØÒªµÄ¹¤×÷¡£linkStateÀíÏëÖеÄÓ¦Óó¡¾°ÈçÏ¡£
export default
class App extends Component {
constructor() {
super();
this.state = {
text: 'initial'
}
}
handleChange = e => {
this.setState({
text: e.target.value
})
}
render({desc}, {text}} {
return (
<div>
<input value={text} onChange= {this.linkState('text',
'target.value')}>
<div>{text}</div>
</div>
)
}
} |
È»¶ølinkStateµÄʵÏÖ·½Ê½¡£¡£¡£ÊÇÔÚ×é¼þ³õʼ»¯µÄʱºòΪÿ¸ö»Øµ÷´´½¨±Õ°ü£¬°ó¶¨this£¬Í¬Ê±´´½¨Ò»¸öʵÀýÊôÐÔ½«°ó¶¨ºó»Øµ÷º¯Êý»º´æÆðÀ´£¬ÕâÑùÔÙ´ÎrenderµÄʱºò¾Í²»ÐèÒªÔٴΰ󶨡£Êµ¼ÊЧ¹ûµÈͬÓÚÔÚ×é¼þµÄconstructorÖа󶨡£ÞÏÞÎÖ®´¦ÔÚÓÚ£¬linkStateÄÚ²¿Ö»ÊµÏÖÁËsetState²Ù×÷£¬Í¬Ê±Ò²²»Ö§³Ö×Ô¶¨Òå²ÎÊý£¬Ê¹Óó¡¾°±È½ÏÓÐÏÞ¡£
//linkStateÔ´Âë
//»º´æ»Øµ÷
linkState(key, eventPath) {
let c = this._linkedStates || (this._linkedStates
= {});
return c[key+eventPath] || (c[key+eventPath] =
createLinkedState(this, key, eventPath));
}
//Ê×´Î×¢²á»Øµ÷µÄʱºò´´½¨±Õ°ü
export function createLinkedState(component,
key, eventPath) {
let path = key.split('.');
return function(e) {
let t = e && e.target || this,
state = {},
obj = state,
v = isString(eventPath) ? delve(e, eventPath)
: t.nodeName ? (t.type.match(/^che|rad/) ? t.checked
: t.value) : e,
i = 0;
for ( ; i<path.length-1; i++) {
obj = obj[path[i]] || (obj[path[i]] = !i &&
component.state[path[i]] || {});
}
obj[path[i]] = v;
component.setState(state);
};
}
|
ÅúÁ¿¸üÐÂ
PreactʵÏÖÁË×é¼þµÄÅúÁ¿¸üУ¬¾ßÌåʵÏÖ˼·¾ÍÊÇÿ´ÎÖ´ÐÐstate or props¸üÐÂ֮ʱ£¬¶ÔÓ¦µÄÊôÐԻᱻÁ¢¿Ì¸üУ¬µ«ÊÇ»ùÓÚnew
state or propsµÄäÖȾ²Ù×÷»á±»push½øµ½Ò»¸ö¸üжÓÁÐÖУ¬ÔÚµ±Ç°event loopµÄ×îºó»òÕßÊÇÔÚÏÂÒ»¸öevent
loopµÄ¿ªÊ¼£¬²Å»á½«¶ÓÁÐÖеIJÙ×÷Ò»Ò»Ö´ÐС£Í¬Ò»¸ö×é¼þ״̬µÄ¶à´Î¸üУ¬²»»áÖØ¸´½øÈë¶ÓÁС£ÈçÏÂͼËùʾ£¬ÊôÐÔ¸üÐÂÖ®ºó£¬×é¼þäÖȾ֮ǰ£¬_dirtyֵΪtrue£¬Òò´Ë£¬×é¼þäÖȾ֮ǰºóÐøµÄÊôÐÔ¸üвÙ×÷¶¼²»»áʹ×é¼þÖØ¸´Èë¶Ó¡£
//¸üжÓÁÐÔ´Âë
export function enqueueRender(component) {
if (!component._dirty && (component._dirty
= true) && items.push(component)==1)
{
(options.debounceRendering || defer)(rerender);
}
} |
2. hº¯Êý
¹Ø¼ü´Ê£º½ÚµãºÏ²¢
hº¯ÊýµÄ×÷ÓÃÈçͬReact.CreateElement£¬ÓÃÓÚÉú³Évirtual
node¡£Æä½ÓÊܵÄÊäÈë¸ñʽÈçÏ£¬Èý¸ö²ÎÊý·Ö±ðΪ½ÚµãÀàÐÍ£¬½ÚµãÊôÐÔ£¬×ÓÔªËØ¡£
h('a', { href:
'/', h{'span', null, 'Home'}}) |
½ÚµãºÏ²¢
hº¯ÊýÔÚÉú³ÉvnodeµÄ¹ý³ÌÖУ¬»á¶ÔÏàÁڵļòµ¥½Úµã½øÐкϲ¢²Ù×÷£¬Ä¿µÄÊÇΪÁ˼õÉÙ½ÚµãÊýÁ¿£¬¼õÇádiff¸ºµ£¡£
Çë¿´ÏÂÃæµÄÀý×Ó¡£
import { h,
Component } from 'preact';
const innerinnerchildren = [['innerchild2',
'innerchild3'], 'innerchild4'];
const innerchildren = [
<div>
{innerinnerchildren}
</div>,
<span>desc</span>
]
export default class App extends Component
{
render() {
return (
<div>
{innerchildren}
</div>
)
}
}
|

3. Render
¹Ø¼ü´Ê£ºÁ÷³Ì¿ØÖÆ£¬diff×¼±¸
Ê×ÏÈÏȽâÊÍһϣ¬ÕâÀïµÄrenderÄ£¿é·ºÖ¸Õû¸öÁ÷³ÌÖн«vnode²åÈëµ½domÊ÷ÖеIJÙ×÷£¬È»¶øÕâÀà²Ù×÷ÖÐÓÖÓÐÒ»²¿·Ö¹¤×÷±»diffÄ£¿é³Ðµ££¬ËùÒÔʵ¼ÊÉÏrenderÄ£¿éµÄ¸ü¶à³Ðµ£µÄÊÇÁ÷³Ì¿ØÖÆÒÔ¼°½øÈëdiffµÄǰÖù¤×÷¡£
Á÷³Ì¿ØÖÆ
ËùνÁ÷³Ì¿ØÖÆ£¬¾ßÌåµÄÄÚÈÝ·ÖΪÁ½²¿·Ö£¬½ÚµãÀàÐ͵ÄÅжϣ¬ÊÇ×Ô¶¨ÒåµÄ×é¼þ»¹ÊÇÔÉúµÄdom½Úµã£¬äÖȾÀàÐ͵ÄÅжϣ¬ÊÇÊ×´ÎäÖȾ»¹ÊǸüвÙ×÷¡£¸ù¾Ý²»Í¬Çé¿ö£¬Ö¸¶¨²»Í¬µÄäÖȾ·Ïߣ¬Ö´ÐÐÏàÓ¦µÄÉúÃüÖÜÆÚ·½·¨£¬hookº¯ÊýºÍäÖȾÂß¼¡£
Diff×¼±¸
ÈçǰËùÊö£¬PreactÔÚÄÚ´æÖÐֻά³ÖÒ»¿Ã°üº¬¸üÐÂÄÚÈݵÄеÄvirtual
domÊ÷£¬ÁíÒ»¸ö´ú±í±»¸üеľɵÄvirtual domÊ÷ʵ¼ÊÉÏÊÇ´ÓdomÊ÷»¹Ô»ØÀ´µÄ£¬Óë´Ëͬʱ£¬domÊ÷µÄ¸üвÙ×÷Ò²ÊÇÔڱȽϹý³ÌÖУ¬Ò»±ß±È½ÏÒ»±ßpatchµÄ¡£ÎªÁËÈ·±£ÉÏÊö²Ù×÷²»³öÏÖ»ìÂÒ£¬ÔÚÉú³É/¸üеÄdomÊ÷µÄ֮ǰ£¬ÐèÒªÔÚdom½ÚµãÉÏÌí¼ÓһЩ×Ô¶¨ÒåµÄÊôÐԼǼ״̬¡£
//´´½¨×Ô¶¨ÒåÊôÐԼǼ
export function renderComponent (component,
opts, mountAll, isChild) {
if (component._disable) return;
let skip, rendered,
props = component.props,
state = component.state,
context = component.context,
previousProps = component.prevProps || props,
previousState = component.prevState || state,
previousContext = component.prevContext || context,
isUpdate = component.base,
nextBase = component.nextBase,
initialBase = isUpdate || nextBase,
initialChildComponent = component._component,
inst, cbase;
|
4. DiffËã·¨
¹Ø¼ü´Ê£ºDOMÒÀÀµ£¬Disconnected or Not£¬DocumentFragment
diff¹ý³ÌÖ÷Òª·ÖΪÁ½¸ö½×¶Î£¬µÚÒ»¸ö½×¶ÎÊǽ¨Á¢virual nodeÓëdom½ÚµãÖ®¼äµÄ¶ÔÓ¦¹ØÏµ£¬µÚ¶þ¸ö½×¶Î±ãÊǶÔÁ½Õß½øÐбȽϲ¢¸üÐÂdom½Úµã¡£
ÔÚʵ¼ÊÖ´Ðйý³ÌÖУ¬diff²Ù×÷µÄÆðµãÊÇupdate×é¼þµÄ¸ù½ÚµãÓë´ú±íÆäÏÂÒ»¸ö״̬µÄvnode֮ǰµÄ±È½Ï¡£ÕâÒ»²½ÖÐÁ½ÕßÖ®¼äµÄ¶ÔÓ¦¹ØÏµÊ®·ÖÃ÷È·£¬¶øµ½ÁËÏÂÒ»²½£¬ÔòÐèÒªÔÚÁ½ÕßµÄ×ÓÔªËØÖÐÈ·¶¨¶ÔÓ¦¹ØÏµ£¬¾ßÌåµÄ·½·¨ÊÇÊ×ÏȶÔÏàͬkeyÖµµÄ×Ó½ÚµãÅä¶Ô£¬Ö®ºó½«Í¬ÀàÐ͵ĽڵãÅä¶Ô£¬×îºóûÓб»Åä¶ÔµÄvnodeÊÓΪÐÂÌí¼ÓµÄ½Úµã£¬¶øÂäµ¥µÄdom½ÚµãµÄÃüÔËÔòÊDZ»»ØÊÕ¡£
½øÈëµ½¸üн׶ÎÖ®ºó£¬»á¸ù¾Ývirtual nodeµÄÀàÐͺÍdomÊ÷ÖвÎÕÕ½ÚµãµÄÇé¿ö·ÖÀà´¦Àí£¬²¢ÔÚdiffµÄ¹ý³ÌÖÐʵʱµÄ½øÐÐpatch²Ù×÷£¬×îÖÕÉú³ÉеÄdom½Úµã£¬È»ºó¶Ô×Ó½ÚµãµÝ¹é¡£

DiffÁ÷³Ìͼ
DOMÒÀÀµ
¾¹ýÇ°ÃæµÄ½éÉÜ£¬ÏàÐÅ´ó¼Ò¶ÔPreactµÄvirtual domʵÏÖÒѾÓÐÁËÒ»¶¨µÄÁ˽⣬ÕâÀï²»ÔÙ׸Êö¡£ÕâÖÖʵÏÖ·½Ê½£¬ÓŵãÔÚÓÚ×ÜÄÜÕæÊµµÄ·´Ó³Ö®Ç°virtual
domÊ÷µÄÇé¿ö£¬È±µã¾ÍÊÇ´æÔÚÄÚ´æÐ¹Â¶µÄ·çÏÕ¡£
Disconnected or Not
What does Disconnected mean
ÎÒÃǶ¼ÖªµÀ£¬µ±ÎÒÃÇÏòdomÊ÷ÖеĽڵãÖ´ÐÐappendChild£¬removeChild²Ù×÷µÄʱºò£¬Ã¿Ö´ÐÐÒ»´Î£¬¾Í»á´¥·¢Ò»´ÎÒ³ÃæµÄreflow£¬ÕâÊÇÒ»¸ö¾ßÓÐÏ൱¿ªÏúµÄÐÐΪ¡£Òò´Ëµ±ÎÒÃDZØÐëÖ´ÐÐһϵÁÐÕâÑùµÄ²Ù×÷µÄʱºò£¬¿ÉÒÔ²ÉÈ¡ÕâÑùµÄÓÅ»¯ÊֶΣ¬Ê×ÏÈ´´½¨Ò»¸ö½Úµã£¬ÔÚÕâ¸ö½ÚµãÉÏÖ´ÐйýËùÓÐ×Ó½ÚµãµÄappend²Ù×÷Ö®ºó£¬ÔÙ½«ÒÔÕâ¸ö½Úµã×÷Ϊ¸ù½ÚµãµÄ×ÓÊ÷Ò»´ÎÐÔµÄappend»òÕßreplaceµ½domÊ÷ÖУ¬Ö»´¥·¢Ò»´Îreflow£¬¾ÍÍê³ÉÁËÕû¸ö×ÓÊ÷µÄ¸üУ¬ÕâÑùµÄ¸üз½Ê½³ÆÖ®Îªdisconnected¡£
ÓëÖ®Ïà¶Ô£¬ÔÚ´´½¨½ÚµãÖ®ºó£¬Á¢¿Ì½«½Úµã²åÈëµ½domÊ÷ÖУ¬È»ºó¼ÌÐø½øÐÐ×Ó½ÚµãµÄ²Ù×÷£¬Ôò³ÆÖ®Îªconnected¡£
Go ahead to Preact
ÔÚ²ûÃ÷ÁËÕâ¸öǰÌáÖ®ºó£¬ÔÙÀ´¿´PreactµÄʵÏÖ·½Ê½£¬Disconnected or Connected£¬ÊÇÒ»×ùΧ³Ç¡£¾¡¹Ü×÷ÕßÉù³ÆPreactµÄäÖȾ·½Ê½ÊÇdisconnected£¬È»¶øÊÂʵµÄÕæÏàÊÇ£¬not
always true¡£ ´ÓÒ»¸ö¼òµ¥µÄÇé¿ö˵Æð£¬textnodeµÄÖµ±»Ð޸ĻòÕß¾ÉµÄ½Úµã±»Ìæ»»³Étextnode¡£PreactËù×öµÄ¾ÍÊÇ´´½¨Ò»¸ötextnode»òÕßÐÞ¸Ä֮ǰtextnodeµÄnodeValue¡£ËäÈ»¾À½áÕâ¸ö³¡¾°ÊÇûÓÐÒâÒåµÄ£¬µ«ÊÇΪÁËÍêÕûµÄ½éÉÜdiffÁ÷³Ì£¬ÓбØÒªÏÈ˵Ã÷һϡ£
½øÈëÖØµã¡£ÏÈ¿´µÚÒ»¸öÀý×Ó¡£ÎªÁË˵Ã÷ÎÊÌ⣬ÎÒÃÇÓÃÒ»¸öÉÔ΢¼«¶ËµãµÄÀý×Ó¡£
ÔÚÕâ¸öÀý×ÓÖпÉÒÔ¿´µ½£¬µ±ÊäÈëtextÖ®ºó£¬ÓÐÒ»¸ödiv×ÓÊ÷Ïòsection×ÓÊ÷µÄ¸üУ¬ÕâÀïΪÁËÃèÊöÒ»¸ö¼«¶ËÇé¿ö£¬¸üÐÂǰºóµÄ×Ó½ÚµãÊÇÒ»ÑùµÄ¡£
//ÀýÒ» placeholderËùÔÚ×ÓÊ÷Ö»Óиù½Úµã²»Í¬
import { h, Component } from 'preact';
export default class App extends Component
{
constructor() {
super();
this.state = {
text: ''
}
}
handlechang = e => {
this.setState({
text: e.target.value
})
}
render({desc}, { text }) {
return (
<div>
<input value={text} onChange={this.handlechang}/>
{text ? <section key='placeholder'>
<h2>placeholder</h2>
</section>: <div key='placeholder'>
<h2>placeholder</h2>
</div>}
</div>
)
}
}
|
½ÓÏÂÀ´¿´Ò»ÏÂÕë¶ÔÕâÖÖ³¡¾°£¬diff²Ù×÷µÄÏêϸÁ÷³Ì¡£
//ÔÉúdomµÄidiffÂß¼
let out = dom, //×¢ÊÍ1
nodeName = String(vnode.nodeName),
prevSvgMode = isSvgMode,
vchildren = vnode.children;
isSvgMode = nodeName==='svg' ? true : nodeName==='foreignObject'
? false : isSvgMode;
if (!dom) { //×¢ÊÍ2
out = createNode(nodeName, isSvgMode);
}
else if (!isNamedNode(dom, nodeName)) { //×¢ÊÍ3
out = createNode(nodeName, isSvgMode);
while (dom.firstChild) out.appendChild(dom.firstChild);
if (dom.parentNode) dom.parentNode.replaceChild(out,
dom);
recollectNodeTree(dom);
}
//×Ó½ÚµãµÝ¹é
¡¡
else if (vchildren && vchildren.length
|| fc) {
innerDiffNode(out, vchildren, context, mountAll);
}
¡¡ |
ÎÞÂÛ²ÎÓëdiffµÄÔªËØÊÇ×Ô¶¨Òå×é¼þ»¹ÊÇÔÉúdom£¬¾¹ý²ã²ã½â¹¹£¬×îÖÕ¶¼ÊÇÒÔdomµÄÐÎʽ½øÐбȽϡ£Òò´ËÎÒÃÇÖ»ÐèÒª¹Ø×¢ÔÉúdomµÄdiffÂß¼¡£
Ê×ÏÈ¿´×¢ÊÍ1µÄλÖã¬dom±íʾdomÊ÷ÉϵĽڵ㣬Ҳ¾ÍÊÇÒª±»¸üеôµÄ½Úµã£¬vnode¾ÍÊÇ´ýäÖȾµÄÐéÄâ½Úµã¡£ÔÚÀýÒ»ÖУ¬diffµÄÆðµã¾ÍÊÇ×îÍâ²ãµÄdiv£¬Ò²¾ÍÊǵÚÒ»ÂÖµÄdom±äÁ¿£¬Òò´Ë×¢ÊÍ2£¬×¢ÊÍ3´¦µÄÅж¨¾ùΪfalse¡£Ö®ºó»á¶Ôout½ÚµãµÄ×Ó½ÚµãºÍ¶ÔÓ¦µÄvnodeµÄ×Ó½Úµã½øÐеݹéµÄdiff²Ù×÷¡£
ÄÇôÕâÀïÊ×ÏÈ˵Ã÷Á˵ÚÒ»´¦ÎÊÌ⣬äÖȾ²Ù×÷µÄÆðµãʼÖÕÊÇconnected״̬µÄ¡£
if (vlen)
{
for (let i=0; i<vlen; i++) {
vchild = vchildren[i];
child = null;
let key = vchild.key;
// ÏàͬkeyֵƥÅä
if (key!=null) {
if (keyedLen && key in keyed) {
child = keyed[key];
keyed[key] = undefined;
keyedLen--;
}
}
// ÏàͬnodeNameÆ¥Åä
else if (!child && min<childrenLen)
{
for (j=min; j<childrenLen; j++) {
c = children[j];
if (c && isSameNodeType(c, vchild))
{
child = c;
children[j] = undefined;
if (j===childrenLen-1) childrenLen--;
if (j===min) min++;
break;
}
}
}
// vnodeΪsection½Úµãʱ£¬domÊ÷ÖмÈÎÞͬkey½Úµã£¬Ò²ÎÞͬnodeName½Úµã£¬Òò´ËΪnull
child = idiff(child, vchild, context, mountAll);
¡¡ |
×Ó½ÚµãÖ®¼äµÄ¶ÔÓ¦¹ØÏµµÄÈ·Á¢ÒÀ¾Ý£¬ÒªÃ´keyÖµÏàͬ£¬ÒªÃ´nodeNameÏàͬ£¬¿ÉÒÔÖªµÀsectionºÍdivµÄ¹ØÏµ²¢²»Âú×ãÉÏÊöÁ½ÖÖÇé¿ö¡£Òò´Ëµ±ÔٴνøÈëidiff·½·¨µÄʱºò£¬ÔÚ×¢ÊÍ2µÄλÖã¬ÓÉÓÚdom²»´æÔÚ£¬»áн¨Ò»¸ösection½Úµã¸³¸øout£¬ÕâÑùÔٴνøÐÐ×ÓÔªËØdiffµÄʱºò£¬ÓÉÓÚoutÊÇÒ»¸öн¨½Úµã£¬²»°üº¬ÈκÎ×ÓÔªËØ£¬sectionµÄËùÓÐ×ÓÔªËØdiffµÄ¶ÔÏó¶¼ÊÇnull£¬Õâ¾ÍÒâζÕâsectionµÄËùÓÐ×ÓÔªËØ×îºó¶¼ÊDZ»Ð½¨³öÀ´µÄ£¨²»ÂÛÊÇ·ñÉèÖÃÁËkeyÖµ£©£¬¾¡¹ÜËüÃǺ;ɵÄdomÉϵĽڵãһģһÑù¡£¡£¡£ËùÒÔ×ܽáһϾÍÊÇÀýÒ»ÕâÖÖÇé¿ö£¬sectionËùÓеÄ×ӽڵ㶼ÊDZ»Ð½¨³öÀ´µÄ£¬¶ø²»ÊDZ»¸´Óõ쬵«ÊÇÕû¸ö²Ù×÷¹ý³ÌÊÇÔÚdisconnectedÇé¿öϽøÐеġ£

ÄÇôÈç¹û¸øÁ½Õß¼ÓÉÏÏàͬµÄkeyֵĨ£¿
// Àý¶þ£¬×é¼þ½á¹¹Ïàͬ£¬Î¨Ò»µÄÇø±ðÊÇplaceholderËùÔÚ×ÓÊ÷Ìí¼ÓÁËÏàͬµÄkeyÖµ
import { h, Component } from 'preact';
export default class App extends Component
{
constructor() {
super();
this.state = {
text: ''
}
}
handlechang = e => {
this.setState({
text: e.target.value
})
}
render({desc}, { text }) {
return (
<div>
<input value={text} onChange={this.handlechang}/>
{text ? <section key='placeholder'>
<h2>placeholder</h2>
</section>: <div key='placeholder'>
<h2>placeholder</h2>
</div>}
</div>
)
}
}
|
ÒòΪÁ½Õß¾ßÓÐÏàͬµÄkeyÖµ£¬ËùÒÔÔÚvnodeÓëdomÈ·¶¨¶ÔÓ¦¹ØÏµÊ±¿ÉÒԳɹ¦µÄÅä¶Ô£¬½øÈëdiff»·½Ú¡£È»¶øÒ»¸öreplace²Ù×÷ÓÖÈúóÐøµÄËùÓвÙ×÷¶¼±ä³ÉÁËconnected¡£ºÃÏûÏ¢ÊÇÏàͬµÄ×ӽڵ㱻¸´ÓÃÁË¡£
// ÔÉúdomµÄdiffÂß¼
// dom½Úµã£¬¼´div´æÔÚ£¬ÇÒÓëvnode½ÚµãÀàÐÍsection²»Í¬ÀàÐÍ
else if (!isNamedNode(dom, nodeName)) {
out = createNode(nodeName, isSvgMode);
while (dom.firstChild) out.appendChild(dom.firstChild);
if (dom.parentNode) dom.parentNode.replaceChild(out,
dom);
recollectNodeTree(dom);
}
|
DocumentFragment
³ýÈ¥ÉÏÃæ½éÉܹýµÄdisconnected·½·¨£¬»¹¿ÉÒÔͨ¹ýDocumentFragment½«Ò»ÏµÁнڵãÒ»´ÎÐÔ²åÈëdom¡£DocumentFragment
½Úµã²åÈëÎĵµÊ÷ʱ£¬²åÈëµÄ²»ÊÇ DocumentFragment ×ÔÉí£¬¶øÊÇËüµÄËùÓÐ×ÓËï½Úµã¡£ÕâʹµÃ
DocumentFragment ³ÉÁËÓÐÓõÄռλ·û£¬ÔÝʱ´æ·ÅÄÇЩһ´Î²åÈëÎĵµµÄ½Úµã¡£githubÉÏÒ²ÓÐÈËÏò×÷ÕßÌá³öÁËͬÑùµÄÎÊÌ⣬×÷Õß±íʾËûÔø¾Ò²³¢ÊÔ¹ýÓÃDocumentFragmentµÄ·½Ê½ÊÔͼ¼õÉÙreflowµÄ´ÎÊý£¬È»¶ø×îÖյĽá¹ûÈ´ÁîÈËÒâÍâ¡£

ÉÏͼΪ×÷Õß±àдµÄ²âÊÔ°¸ÀýµÄÐÔÄܶԱÈͼ£¬ºá×ø±êΪOperation per second£¬ÊýÖµÔ½´ó´ú±íÖ´ÐÐЧÂÊÔ½¸ß¡£¿ÉÒÔ¿´³öÎÞÂÛconnected»¹ÊÇdisconnectedµÄÇé¿ö£¬DocumentFragementµÄ±íÏÖ¶¼¸ü²î¡£¾ßÌåÔÒò»¹Óдý¿¼¾¿¡£BenchMarkÔÁ´½Ó¡£
5. »ØÊÕ»úÖÆ
¹Ø¼ü´Ê£º»ØÊÕ³Ø&Enhanced Mount
»ØÊÕ³Ø&Enhanced Mount
ÔÚ½«½Úµã´ÓdomÖÐÒÆ³ýʱ£¬²»»á½«½ÚµãÖ±½Óɾ³ý£¬¶øÊÇ»á¸ù¾Ý½ÚµãÀàÐÍ£¨×é¼þ or node£©£¬Ö´ÐÐһЩÇåÀíÂß¼Ö®ºó£¬·Ö±ð´æÈëµ½Á½¸ö»ØÊÕ³ØÖС£ÔÚÿ´ÎÖ´ÐÐMount²Ù×÷µÄʱºò£¬´´½¨·½·¨»áÔÚ»ØÊÕ³ØÀïѰÕÒͬÀàÐͽڵ㣬һµ©ÕÒµ½ÕâÑùµÄͬÀà½Úµã£¬Ëü»á±»×÷Ϊ´ý¸üеIJÎÕսڵ㴫ÈëdiffËã·¨ÖУ¬ÕâÑùÔÙºóÐøµÄ±È½Ï¹ý³ÌÖУ¬À´×Ô»ØÊճصĽڵã»á±»×÷ΪÔÐͽøÐÐpatch¸ÄÔ죬²úÉúеĽڵ㡣Ï൱ÓÚ±äMountΪUpdate£¬´Ó¶ø±ÜÃâ´ÓÁã¹¹½¨µÄ¶îÍ⿪Ïú¡£
ÏÖʵµÄ½á¾ÖÍùÍùûÓÐͯ»°¹ÊʰãÃÀºÃ£¬»ØÊÕ»úÖÆ×îÖÕ»¹ÊdzöÏÖÁËÒâÍâ¡£°¸·¢ÏÖ³¡´«ËÍÃÅ£¬»ØÊÕ»úÖÆ»áÔÚijЩÇé¿öϵ¼Ö½ڵ㱻´íÎóµÄ¸´Óá¡ËùÒÔ£¬Èçͬ·¢Ñ×µÄÀ»Î²£¬¿ÉÄÜºÜ¿ì»ØÊÕ»úÖÆ¾Í»á´ÓÎÒÃǵÄÊÓÏßÀïÏûʧÁË¡£
|