Skip to content

Commit eb66ed6

Browse files
author
陈进
committed
React源码解析之Commit第二子阶段「mutation」(上)
1 parent 5dc1c5d commit eb66ed6

File tree

6 files changed

+355
-158
lines changed

6 files changed

+355
-158
lines changed

.idea/workspace.xml

Lines changed: 175 additions & 114 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

react16.8.6/packages/react-dom/src/client/ReactDOMComponent.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ export function trapClickOnNonInteractiveElement(node: HTMLElement) {
321321
// TODO: Only do this for the relevant Safaris maybe?
322322
node.onclick = noop;
323323
}
324+
324325
//初始化 DOM 对象的内部属性
325326
function setInitialDOMProperties(
326327
tag: string,
@@ -395,24 +396,39 @@ function setInitialDOMProperties(
395396
}
396397
}
397398
}
398-
399+
//更新 DOM 属性
399400
function updateDOMProperties(
400401
domElement: Element,
401402
updatePayload: Array<any>,
402403
wasCustomComponentTag: boolean,
403404
isCustomComponentTag: boolean,
404405
): void {
405406
// TODO: Handle wasCustomComponentTag
407+
//遍历更新队列,注意 i=i+2,因为 updatePayload 是这样的:['style',{height:14},'__html',xxxx,...]
408+
//关于updatePayload,请看:
409+
// [React源码解析之HostComponent的更新(上)](https://juejin.im/post/5e5c5e1051882549003d1fc7)中的「四、diffProperties」
406410
for (let i = 0; i < updatePayload.length; i += 2) {
411+
//要更新的属性
407412
const propKey = updatePayload[i];
413+
//要更新的值
408414
const propValue = updatePayload[i + 1];
415+
//要更新style 属性的话,则执行setValueForStyles
409416
if (propKey === STYLE) {
417+
// 设置 style 的值,请看:
418+
// [React源码解析之HostComponent的更新(下)](https://juejin.im/post/5e65f86f6fb9a07cdc600e09)中的「八、setInitialProperties」中的第八点
410419
setValueForStyles(domElement, propValue);
411-
} else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
420+
}
421+
422+
else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
423+
// 设置innerHTML属性,请看:
424+
// [React源码解析之HostComponent的更新(下)](https://juejin.im/post/5e65f86f6fb9a07cdc600e09)中的「八、setInitialProperties」中的第八点
412425
setInnerHTML(domElement, propValue);
413426
} else if (propKey === CHILDREN) {
427+
//设置textContent属性,请看:
428+
// [React源码解析之HostComponent的更新(下)](https://juejin.im/post/5e65f86f6fb9a07cdc600e09)中的「八、setInitialProperties」中的第八点
414429
setTextContent(domElement, propValue);
415430
} else {
431+
//为DOM节点设置属性值,即 setAttribute
416432
setValueForProperty(domElement, propKey, propValue, isCustomComponentTag);
417433
}
418434
}
@@ -1004,15 +1020,21 @@ export function updateProperties(
10041020
// Update checked *before* name.
10051021
// In the middle of an update, it is possible to have multiple checked.
10061022
// When a checked radio tries to change name, browser makes another radio's checked false.
1023+
//如果是 radio 标签的话
10071024
if (
10081025
tag === 'input' &&
10091026
nextRawProps.type === 'radio' &&
10101027
nextRawProps.name != null
10111028
) {
1029+
//单选按钮的相关操作,可不看
10121030
ReactDOMInputUpdateChecked(domElement, nextRawProps);
10131031
}
1032+
//判断是否是自定义的 DOM 标签,具体请看:
1033+
//[React源码解析之HostComponent的更新(下)](https://mp.weixin.qq.com/s/aB8jRVFzJ6EkkIqPVF3r1Q)中的「八、setInitialProperties」
10141034

1035+
//之前是否是自定义标签
10151036
const wasCustomComponentTag = isCustomComponent(tag, lastRawProps);
1037+
//待更新的是否是自定义标签
10161038
const isCustomComponentTag = isCustomComponent(tag, nextRawProps);
10171039
// Apply the diff.
10181040
updateDOMProperties(
@@ -1024,6 +1046,7 @@ export function updateProperties(
10241046

10251047
// TODO: Ensure that an update gets scheduled if any of the special props
10261048
// changed.
1049+
//特殊标签的特殊处理,可不看
10271050
switch (tag) {
10281051
case 'input':
10291052
// Update the wrapper around inputs *after* updating props. This has to

react16.8.6/packages/react-dom/src/client/ReactDOMHostConfig.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ export function commitMount(
373373
}
374374
}
375375

376+
//进行节点的更新
376377
export function commitUpdate(
377378
domElement: Instance,
378379
updatePayload: Array<mixed>,
@@ -383,12 +384,16 @@ export function commitUpdate(
383384
): void {
384385
// Update the props handle so that we know which props are the ones with
385386
// with current event handlers.
387+
388+
//挂载属性:node[internalEventHandlersKey] = props;
386389
updateFiberProps(domElement, newProps);
387390
// Apply the diff to the DOM node.
391+
//更新 DOM 属性
388392
updateProperties(domElement, updatePayload, type, oldProps, newProps);
389393
}
390-
394+
//将该 DOM 节点的 value 设置为 ''
391395
export function resetTextContent(domElement: Instance): void {
396+
//给 DOM 节点设置text
392397
setTextContent(domElement, '');
393398
}
394399

react16.8.6/packages/react-dom/src/client/setTextContent.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ import {TEXT_NODE} from '../shared/HTMLNodeType';
1818
* @param {string} text
1919
* @internal
2020
*/
21+
//给 DOM 节点设置text
2122
let setTextContent = function(node: Element, text: string): void {
2223
if (text) {
2324
let firstChild = node.firstChild;
24-
25+
//如果只有一个子节点且是文字节点,将其value置为 text
2526
if (
2627
firstChild &&
2728
firstChild === node.lastChild &&
@@ -31,6 +32,7 @@ let setTextContent = function(node: Element, text: string): void {
3132
return;
3233
}
3334
}
35+
//text 为'',则直接执行这一步
3436
node.textContent = text;
3537
};
3638

0 commit comments

Comments
 (0)