Upload
chien-wei-huang
View
191
Download
3
Embed Size (px)
Citation preview
DOM and Browser PatternsCarl
2016/02/23
1
Outline
Separation of Concerns
DOM Scripting
Events
Long-Running Scripts
Remote Scripting
Deploying JavaScript
Loading Strategies
Summary2
Separation of Concerns
Content
HTML
Presentation
CSS
Behavior
JavaScript
3
Separation of Concerns
Test without CSS/JS
No inline event handlers or style(?)
ReactJS JSX: <button onClick={this.test(this)}>Submit</button>
Semantically HTML elements
4
Capability Detection
Check function exist instead of check browser agent
// antipatternif (navigator.userAgent.indexOf('MSIE') !== −1) { document.attachEvent('onclick', console.log); }
// betterif (document.attachEvent) { document.attachEvent('onclick', console.log); }// or even more specificif (typeof document.attachEvent !== "undefined") { document.attachEvent('onclick', console.log); } 5
DOM Scriping
DOM Access
DOM Manipulation
6
DOM Access
Avoiding DOM access in loops
Assigning DOM references to local variables and working with the locals
Using selectors API where available
Caching the length when iterating over HTML collections (see Chapter 2)
7
Avoiding DOM access in loops// antipatternfor (var i = 0; i < 100; i += 1) { document.getElementById("result").innerHTML += i + ", "; }// better - update a local variablevar i, content = "";for (i = 0; i < 100; i += 1) { content += i + ","; }document.getElementById("result").innerHTML += content;
8
Assigning DOM references to local variables and working with the locals
// antipatternvar padding = document.getElementById("result").style.padding,margin = document.getElementById("result").style.margin;
// bettervar style = document.getElementById("result").style,padding = style.padding,margin = style.margin;
9
Using selectors API where availabledocument.querySelector("ul .selected");document.querySelectorAll("#widget .class");https://developer.mozilla.org/zh-TW/docs/Web/API/document.querySelector
Faster than jQuery Dom method
document.getElementById(myid) is still the fatest
https://jsperf.com/getelementbyid-vs-queryselector/25
10
DOM Manipulation(Document Fragment)// antipattern// appending nodes as they are createdvar p, t;p = document.createElement('p');document.body.appendChild(p);p = document.createElement('p');document.body.appendChild(p);
11
DOM Manipulation(Document Fragment)var p, t, frag;frag = document.createDocumentFragment();p = document.createElement('p');frag.appendChild(p);p = document.createElement('p');frag.appendChild(p);document.body.appendChild(frag);
https://developer.mozilla.org/en-US/docs/Web/API/Document/createDocumentFragment
12
DOM Manipulation(Document Fragment)var oldnode = document.getElementById('result'), clone = oldnode.cloneNode(true); // cloneNode(true) if the children of the node should also be cloned, or false to clone only the specified node. https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode
// work with the clone...
// when you're done:oldnode.parentNode.replaceChild(clone, oldnode);
13
Events
Events Handling
Event Delegation
14
Events Handling
Use addEventListener/attachEvent instead of onxxx(ex: onclick)
onxxx bind to only one event
15
Event Delegation
Bind event to parent instead of child
Use event.target to check the target node
Pros
reduce event listeners
Cons
hard to find the event listener from browser developer tool
Demo
http://codepen.io/anon/pen/vLqvaV 16
Event Delegation
ReactJS JSX: <button onClick={this.test(this)}>Submit</button>
React use single top level event listener
https://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#under-the-hood-autobinding-and-event-delegation
17
Long-Running Scripts (setTimeout)
var timer1 = setTimeout(myfunction1, 50);var timer2 = setTimeout(myfunction2, 100);var timer3 = setTimeout(myfunction3, 150);
18
Long-Running Scripts (Web Wrokers)var ww = new Worker('my_web_worker.js'); ww.onmessage = function (event) { document.body.innerHTML += "<p>message from the background thread: " + event.data + "</p>";
};
// Outputmessage from the background thread: hello theremessage from the background thread: halfway there, `tmp` is now 3749999975000001message from the background thread: all done
19
// my_web_worker.jsvar end = 1e8, tmp = 1;postMessage('hello there');while (end) { end -= 1; tmp += end; if (end === 5e7) { // 5e7 is the half of 1e8 postMessage('halfway there, `tmp` is now ' + tmp); }}postMessage('all done');
Remote Scripting
XMLHttpRequest
JSONP
Frames and Image Beacons
20
XMLHttpRequestvar xhr = new XMLHttpRequest();xhr.onreadystatechange = function () { if (xhr.readyState !== 4) { // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState return false; } if (xhr.status !== 200) { alert("Error, status code: " + xhr.status); return false; } document.body.innerHTML += "<pre>" + xhr.responseText + "<\/pre>"; };xhr.open("GET", "page.html", true); xhr.send("");
21
JSONPNot restricted by the same-domain policy (Use script tag)
Often JSON wrapped in a function call
https://zh.wikipedia.org/wiki/JSONP
var script = document.createElement("script"); script.src = “http://remote.org/getdata.php?callback=myHandler”; document.body.appendChild(script);
// Output of http://example.org/getdata.php?callback=myHandlermyHandler({“hello”: “world”});
22