22
DOM and Browser Patterns Carl 2016/02/23 1

JavaScript patterns chapter 8 of mine

Embed Size (px)

Citation preview

Page 1: JavaScript patterns chapter 8 of mine

DOM and Browser PatternsCarl

2016/02/23

1

Page 2: JavaScript patterns chapter 8 of mine

Outline

Separation of Concerns

DOM Scripting

Events

Long-Running Scripts

Remote Scripting

Deploying JavaScript

Loading Strategies

Summary2

Page 3: JavaScript patterns chapter 8 of mine

Separation of Concerns

Content

HTML

Presentation

CSS

Behavior

JavaScript

3

Page 4: JavaScript patterns chapter 8 of mine

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

Page 5: JavaScript patterns chapter 8 of mine

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

Page 6: JavaScript patterns chapter 8 of mine

DOM Scriping

DOM Access

DOM Manipulation

6

Page 7: JavaScript patterns chapter 8 of mine

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

Page 8: JavaScript patterns chapter 8 of mine

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

Page 9: JavaScript patterns chapter 8 of mine

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

Page 10: JavaScript patterns chapter 8 of mine

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

Page 11: JavaScript patterns chapter 8 of mine

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

Page 12: JavaScript patterns chapter 8 of mine

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

Page 13: JavaScript patterns chapter 8 of mine

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

Page 14: JavaScript patterns chapter 8 of mine

Events

Events Handling

Event Delegation

14

Page 15: JavaScript patterns chapter 8 of mine

Events Handling

Use addEventListener/attachEvent instead of onxxx(ex: onclick)

onxxx bind to only one event

15

Page 16: JavaScript patterns chapter 8 of mine

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

Page 17: JavaScript patterns chapter 8 of mine

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

Page 18: JavaScript patterns chapter 8 of mine

Long-Running Scripts (setTimeout)

var timer1 = setTimeout(myfunction1, 50);var timer2 = setTimeout(myfunction2, 100);var timer3 = setTimeout(myfunction3, 150);

18

Page 19: JavaScript patterns chapter 8 of mine

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');

Page 20: JavaScript patterns chapter 8 of mine

Remote Scripting

XMLHttpRequest

JSONP

Frames and Image Beacons

20

Page 21: JavaScript patterns chapter 8 of mine

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

Page 22: JavaScript patterns chapter 8 of mine

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