title | comments | date | type | categories | tags | ||
---|---|---|---|---|---|---|---|
Common DOM Manipulations |
true |
2018-10-15 10:40:29 -0700 |
categories |
Full stack |
|
window
: a global object, and everything runs under it, includingdocument
- global variables,
- global functions,
location
history
setTimeout
- ajax call (XMLHttpRequest),
console
localStorage
documnet
: represents the DOM and DOM is the object oriented representation of the html markup you have written;- All the nodes are part of document. Hence you can use getElementById or addEventListener on document.
window.onload
: When EVERYTHING is loaded. DOM is ready and all the contents including images, css, scripts, sub-frames, etc. finished loaded.document.onload
: once the DOM is loaded, regardless of the css, scripts,...
-
attribute
: belongs to HTML tag, is static after being initialized -
property
: belongs to DOM node, is dynamic while interact with its element -
<input id="my-input" type="text" value="Name:"> <script> var myInput = document.getElementById('my-input'); myInput.getAttribute('value'); //"Name:" myInput.value; //'my dude' </script>
function addClass(selector, className){
var elm = document.querySelector(selector);
if (elm){
elm.classList.add(className);
}
}
function isDescendant(parent, child){
while(child.parentNode ){
if(child.parentNode == parent)
return true;
else
child = child.parentNode;
}
return false;
}
-
innerHTML
: browser removes all the current children of the elements. Parse the string and assign the parsed string to the element as children. So, Slow!-
var ul = document.getElementById('myList'); el.innerHTML = '<li>Only one item</li>';
-
-
appendChild
: you create a new Element. Since you are creating it, browser doesnt have to parse string and there is no invalid html. so, Fast!-
var li = document.createElement("li"); var text = document.createTextNode('Only one Item'); li.appendChild(text); ul.appendChild(li);
-
-
documentFragment
a lightweight or minimal part of a DOM or a subtree of a DOM tree. -
It is very helpful when you are manipulating a part of DOM for multiple times.
-
It becomes expensive to hit a certain portion of DOM for hundreds time. You might cause reflow for hundred times. Stay tuned for reflow.
-
BAD practice:
-
//bad practice. you are hitting the DOM every single time var list = ['foo', 'bar', 'baz', ... ], el, text; for (var i = 0; i < list.length; i++) { el = document.createElement('li'); text = document.createTextNode(list[i]); el.appendChild(text); document.body.appendChild(el); }
-
-
GOOD practice:
-
//good practice. you causing reflow one time var fragment = document.createDocumentFragment(), list = ['foo', 'bar', 'baz', ...], el, text; for (var i = 0; i < list.length; i++) { el = document.createElement('li'); text = document.createTextNode(list[i]); el.appendChild(text); fragment.appendChild(el); } document.body.appendChild(fragment);
-
- [reflow] : flow of the elements in the page is changed due to change size or position
- When you change size or position of an element in the page, all the elements after it has to change their position according to the changes you made.
- For example, if you change height on an element, all the elements under it has to move down in the page to accomodate a change in height.
- Reasons:
- change layout (geometry of the page)
- resize the window
- change height/width of any element
- changing font, or font size
- move DOM element (animation)
- adding or removing stylesheet
- calculating offset height or offset width
display: none;
- It happens when you change the look of an element without changing the size and shape. This doesn't cause reflow as geometry of the element didn't changed.
- Reasons:
- change background color
- change text color
- visibility hidden
Create a button that is destroyed by clicking on it but two new buttons are created in it's place.
<div id="wrapper">
<button id="doubleHolder" class="double">double</button>
</div>
<script>
document.getElementById('doubleHolder').addEventListener('click', function (e) {
var btn = document.createElement('button');
btn.setAttribute('class', 'double');
btn.innerHTML = 'double1';
var btn2 = document.createElement('button');
btn2.setAttribute('class', 'double');
btn2.innerHTML = 'double2';
let wrapper = document.getElementById('wrapper')
wrapper.appendChild(btn);
wrapper.appendChild(btn2);
wrapper.removeChild(e.target);
});
</script>
-
innerHTML parses content as HTML and takes longer. Also vulnerable to XSS attacks
-
textContent uses straight text, does not parse HTML, and is faster.
-
// Given the following HTML fragment: // <div id="divA">This is <span>some</span> text</div> // Get the text content: var text = document.getElementById("divA").textContent; // |text| is set to "This is some text". // Set the text content: document.getElementById("divA").textContent = "This is some text"; // The HTML for divA is now: // <div id="divA">This is some text</div> Polyfill
-
-
innerText Takes styles into consideration. It won't get hidden text for instance.: Bad, causing reflow !
defer
&async
are only effective in<script>
tag. HTML parser will ignoredefer
andasync
keyword for inline script (script that does not have a src attribute).- normal: When you have a plain script tag (no defer or async keyword), parser will pause parsing, script would be downloaded and exectuted. After that parsing resume
- async: downloading script won't affect HTML paring, but executing will pause HTML parsing. Once downloaded, script begin to executed, will pause HTML parsing
- defer: downloading script won't affect HTML paring, also executing won't affect HTML parsing. The script with
defer
will executed util HTML finish parsing