-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from nparashar150/render/diffing
Setup basic diffing on every render.
- Loading branch information
Showing
8 changed files
with
228 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,124 @@ | ||
/** | ||
* | ||
* @param {HTMLElement} element | ||
* @param {String} containerId | ||
* | ||
* @param {HTMLElement} element | ||
* @param {String} containerId | ||
*/ | ||
export const render = (element, containerId) => { | ||
const root = document.getElementById(containerId); | ||
root.appendChild(element); | ||
if (!root.firstChild) { | ||
return root.appendChild(element); | ||
} | ||
const oldNode = root.firstChild; | ||
const newNode = element; | ||
|
||
diff(oldNode, newNode); | ||
}; | ||
|
||
/** | ||
* | ||
* @param {NodeList} oldNode | ||
* @param {NodeList} newNode | ||
*/ | ||
export const diff = (oldNode, newNode) => { | ||
// Reference to nodeTypes: https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType | ||
|
||
// If the old node is a text node and the new node is a text node | ||
if (oldNode.nodeType === 3 && newNode.nodeType === 3) { | ||
// If the text content is different | ||
if (oldNode.textContent !== newNode.textContent) { | ||
// Update the text content | ||
oldNode.textContent = newNode.textContent; | ||
} | ||
} | ||
|
||
// If the old node is a text node and the new node is not a text node | ||
if (oldNode.nodeType === 3 && newNode.nodeType !== 3) { | ||
// Replace the old node with the new node | ||
oldNode.replaceWith(newNode); | ||
} | ||
|
||
// If the old node is not a text node and the new node is a text node | ||
if (oldNode.nodeType !== 3 && newNode.nodeType === 3) { | ||
// Replace the old node with the new node | ||
oldNode.replaceWith(newNode); | ||
} | ||
|
||
// If the old node is not a text node and the new node is not a text node | ||
if (oldNode.nodeType !== 3 && newNode.nodeType !== 3) { | ||
// If the tag names are different | ||
if (oldNode.tagName !== newNode.tagName) { | ||
// Replace the old node with the new node | ||
oldNode.replaceWith(newNode); | ||
} | ||
|
||
// If the tag names are the same | ||
if (oldNode.tagName === newNode.tagName) { | ||
// Update the attributes | ||
updateAttributes(oldNode, newNode); | ||
|
||
// Update the children | ||
updateChildren(oldNode, newNode); | ||
} | ||
} | ||
}; | ||
|
||
/** | ||
* | ||
* @param {NodeList} oldNode | ||
* @param {NodeList} newNode | ||
*/ | ||
export const updateAttributes = (oldNode, newNode) => { | ||
// Reference to attributes: https://developer.mozilla.org/en-US/docs/Web/API/Element/attributes | ||
|
||
// Get the old attributes | ||
const oldAttributes = Array.from(oldNode.attributes); | ||
|
||
// Get the new attributes | ||
const newAttributes = Array.from(newNode.attributes); | ||
|
||
// Remove the old attributes | ||
oldAttributes.forEach((attribute) => { | ||
oldNode.removeAttribute(attribute.name); | ||
}); | ||
|
||
// Add the new attributes | ||
newAttributes.forEach((attribute) => { | ||
oldNode.setAttribute(attribute.name, attribute.value); | ||
}); | ||
}; | ||
|
||
/** | ||
* | ||
* @param {NodeList} oldNode | ||
* @param {NodeList} newNode | ||
*/ | ||
export const updateChildren = (oldNode, newNode) => { | ||
// Reference to childNodes: https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes | ||
|
||
// Get the old children | ||
const oldChildren = Array.from(oldNode.childNodes); | ||
|
||
// Get the new children | ||
const newChildren = Array.from(newNode.childNodes); | ||
|
||
// If the new node has more children, add them | ||
newChildren.forEach((child, index) => { | ||
if (index >= oldChildren.length) { | ||
oldNode.appendChild(child); | ||
} | ||
}); | ||
|
||
// If the new node has less children, remove them | ||
oldChildren.forEach((child, index) => { | ||
if (index >= newChildren.length) { | ||
oldNode.removeChild(child); | ||
} | ||
}); | ||
|
||
// If the new node has the same number of children, update them | ||
oldChildren.forEach((child, index) => { | ||
if (index < newChildren.length) { | ||
diff(child, newChildren[index]); | ||
} | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/** | ||
* | ||
// * @param {*} initialState | ||
* @param {*} _state | ||
*/ | ||
export const useState = (initialState) => { | ||
let _state = initialState; | ||
const _setState = (newState) => { | ||
if (_state === newState) return; | ||
_state = newState; | ||
return _state; | ||
}; | ||
return [_state, _setState]; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,18 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="UTF-8"> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<link rel="stylesheet" href="./css/styles.css"> | ||
<title>Document</title> | ||
</head> | ||
<body id="root"> | ||
|
||
<body> | ||
<div id="root"></div> | ||
</body> | ||
<script async defer src="./js/own-react-bundle.js"></script> | ||
<script async defer src="./js/useState.js"></script> | ||
|
||
</html> |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
*, | ||
html, | ||
body { | ||
margin: 0; | ||
padding: 0; | ||
box-sizing: border-box; | ||
font-family: monospace; | ||
} | ||
|
||
html, | ||
body { | ||
padding: 1rem; | ||
} | ||
|
||
html, | ||
body, | ||
h1, | ||
h2, | ||
h3, | ||
h4, | ||
h5, | ||
h6, | ||
p { | ||
padding-bottom: 1rem; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,72 @@ | ||
import OwnReact from "../lib/index"; | ||
import Button from "./components/button/button"; | ||
import "./global.css"; | ||
|
||
const App = () => { | ||
return ( | ||
<div id="root2"> | ||
<Button>Click me</Button> | ||
<h1>My First Own React App</h1> | ||
<p> | ||
<div className="testing"> | ||
<h1>My First Own React App with custom Babel and Webpack config</h1> | ||
<p>This is another nesting level</p> | ||
<Button>Click me</Button> | ||
</div> | ||
</p> | ||
</div> | ||
); | ||
}; | ||
OwnReact.render(App(), "root"); | ||
const App2 = () => { | ||
return ( | ||
<div id="root3"> | ||
<h1>My Second Own React App</h1> | ||
<p> | ||
<div className="testing"> | ||
<h1>My Second Own React App with custom Babel and Webpack config</h1> | ||
<p>This is another nesting level</p> | ||
<p>This is another nesting level</p> | ||
<p>This is another nesting level</p> | ||
<Button>Click me second</Button> | ||
</div> | ||
</p> | ||
</div> | ||
); | ||
}; | ||
|
||
const App3 = () => { | ||
return ( | ||
<div id="root4"> | ||
<h1>My Third Own React App</h1> | ||
<p> | ||
<div className="testing"> | ||
<h1>My Third Own React App with custom Babel and Webpack config</h1> | ||
<p>This is another nesting level</p> | ||
<p>This is another another nesting level</p> | ||
<Button>Click me third</Button> | ||
</div> | ||
</p> | ||
</div> | ||
); | ||
}; | ||
|
||
const App4 = () => { | ||
return ( | ||
<div id="root4"> | ||
<h1>My Fourth Own React App</h1> | ||
</div> | ||
); | ||
}; | ||
|
||
OwnReact.render(<App />, "root"); | ||
|
||
setTimeout(() => { | ||
OwnReact.render(<App2 />, "root"); | ||
}, 5000); | ||
|
||
setTimeout(() => { | ||
OwnReact.render(<App3 />, "root"); | ||
}, 10000); | ||
|
||
setTimeout(() => { | ||
OwnReact.render(<App4 />, "root"); | ||
}, 15000); |