SlideShare uma empresa Scribd logo
1 de 151
Baixar para ler offline
Stop Writing Javascript
Frameworks
Joe Gregorio
@bitworking
bit.ly/zf-preso-2
● I am employed by Google
● This talk does not represent the opinion of
Google
Caveats
● Code is for exposition purposes only.
Caveats
● Those expecting magic and/or cleverness.
Apologies in Advance
● Open Source https://skia.org
● 2D Graphics Library
○ CPU
○ GPU
○ PDF
About Skia
● Chrome
● Android
● Firefox
● Flutter.io
● Sublime Text 3
● ...
About Skia
● Hidden Gems
○ PathOps
https://skia.org/dev/present/pathops
○ SkNx https://skia.org/dev/contrib/simd
About Skia
● Infrastructure
○ Run the Tests
○ Tools for Analysis
■ 500,000 Images/Commit
■ 260,000 Perf Metrics/Commit
About Me
● Go
● Polymer
● Google Compute Engine
● Open Source
○ https://skia.googlesource.com/buildbot/
About Skia Infra
● Build fast
● Iterate quickly
● Maintain robustly
● Do things at scale
Context
Stop Writing Javascript
Frameworks
http://bitworking.org/news/2014/05/zero_framework_manifesto
using hyperbole
https://xkcd.com/386/
Slightly Hyperbolic Title
Things I didn't say
● Stop innovating.
● Stop using Javascript libraries.
● Stop using tools.
● I have all the answers.
Alternate Accurate Titles
● Stop Using Javascript Frameworks
● Start writing reusable orthogonally
composable units of HTML+CSS+JS
Stop Writing Using
Javascript Frameworks
Joe Gregorio
@bitworking
What do I mean by
"framework"?
gist -> library -> framework
gist -> library -> framework
Trouble starts here
● HTML
● CSS
● JS
● HTML
● CSS
● JS
GWT
● HTML
● CSS
● JS
There was a time for
frameworks
Remember the IE box model?
https://en.wikipedia.org/wiki/Internet_Explorer_box_model_bug
Remember the IE event model?
https://en.wikipedia.org/wiki/DOM_events#Microsoft-specific_model
Remember the Netscape layer tag?
<LAYER ID=layer1 TOP=20pt LEFT=5pt BGCOLOR="#CC00EE"
WIDTH=200>
<H1>Layer 1</H1>
<P>Lots of content for this layer.</P>
<IMG SRC=violets.jpg align=right>
<P>Content for layer 1.</P>
<P>More Content for layer 1.</P>
</LAYER>
http://web.archive.org/web/20040929103224/http://developer.netscape.com/docs/manuals/communicator/dynhtml/index.htm
There was no consistent model for
interacting with the browser.
The situation has improved
http://caniuse.com/#feat=svg
So that weakens one reason
to use a framework.
Polyfills
The "import __future__" for
the web.
Framework
Polyfills
Fill in the
potholes.
But what about all the other
benefits a framework brings?
Abstractions are Leaky
Abstractions are Abstract
https://upload.wikimedia.org/wikipedia/commons/a/ac/Iceberg.jpg
Reuse
Busy porting my Dojo widgets
to Backbone.
Angular 1.0 -> 2.0
Framework
Polyfills
Fill in the
potholes.
Code organization
?
Framework
Polyfills
Web
Components
Fill in the
potholes.
Code organization
Web Components
● HTML Templates
● HTML Imports
● Custom Elements
● Shadow DOM
Web Components
● HTML Templates
● HTML Imports
● Custom Elements
● Shadow DOM
HTML Templates
● Now part of HTML spec
HTML Templates
HTML Templates
● <template>...</template>
● Content is parsed by browser.
● Content is not rendered (invisible to user).
● Content is hidden (invisible to
querySelector).
● Content is inert. (JS doesn't run)
<template id=t>
<div>Hello World!</div>
</template>
<script>
var node = document.importNode(
document.querySelector('#t').content, true);
document.body.appendChild(node);
</script>
<template id=t>
<div>Hello World!</div>
</template>
<script>
var node = document.importNode(
document.querySelector('#t').content, true);
document.body.appendChild(node);
</script>
<template id=t>
<div>Hello World!</div>
</template>
<script>
var node = document.importNode(
document.querySelector('#t').content, true);
document.body.appendChild(node);
</script>
<template id=t>
<div>Hello World!</div>
</template>
<script>
var node = document.importNode(
document.querySelector('#t').content, true);
document.body.appendChild(node);
</script>
<template id=t>
<div>Hello World!</div>
</template>
<script>
var node = document.importNode(
document.querySelector('#t').content, true);
document.body.appendChild(node);
</script>
bit.ly/zf-template
HTML Imports
● <link rel="import" href="">
● Oddly slightly contentious.
● Brilliant for code organization, keep HTML,
CSS, and JS together in one file.
HTML Imports
● Are de-dup'd
● Can contain anything an HTML file can
contain (HTML, CSS, JS)
● Scripts are executed in the context of the
window that imported them
<template id=t>
<div>
Hello World!
</div>
</template>
<script>
(function() {
var doc = document.currentScript.ownerDocument;
var node = document.importNode(
doc.querySelector( '#t').content, true);
document.body.appendChild(node);
})();
</script>
import.html
<template id=t>
<div>
Hello World!
</div>
</template>
<script>
(function() {
var doc = document.currentScript.ownerDocument;
var node = document.importNode(
doc.querySelector('#t').content, true);
document.body.appendChild(node);
})();
</script>
import.html
<template id=t>
<div>
Hello World!
</div>
</template>
<script>
(function() {
var doc = document.currentScript.ownerDocument;
var node = document.importNode(
doc.querySelector('#t').content, true);
document.body.appendChild(node);
})();
</script>
import.html
<template id=t>
<div>
Hello World!
</div>
</template>
<script>
(function() {
var doc = document.currentScript.ownerDocument;
var node = document.importNode(
doc.querySelector('#t').content, true);
document.body.appendChild(node);
})();
</script>
import.html
<template id=t>
<div>
Hello World!
</div>
</template>
<script>
(function() {
var doc = document.currentScript.ownerDocument;
var node = document.importNode(
doc.querySelector('#t').content, true);
document.body.appendChild(node);
})();
</script>
import.html
<html>
<head>
<script src="webcomponents.js"></script>
<link rel="import" href="import.html">
</head>
<body>
</body>
</html>
bit.ly/zf-html-imports-tmpl
index.html
<html>
<head>
<script src="webcomponents.js"></script>
<link rel="import" href="import.html">
</head>
<body>
</body>
</html>
bit.ly/zf-html-imports-tmpl
index.html
http://webcomponents.org
<html>
<head>
<script src="webcomponents-lite.js"></script>
<link rel="import" href="import.html">
</head>
<body>
</body>
</html>
bit.ly/zf-html-imports-tmpl
index.html
<html>
<head>
<script src="webcomponents.js"></script>
<link rel="import" href="import.html">
</head>
<body>
</body>
</html>
bit.ly/zf-html-imports-tmpl
index.html
Context = function() {
this.doc = (document.currentScript ||document._currentScript).ownerDocument;
};
Context.prototype. import = function(id) {
return document.importNode(this.doc.querySelector( '#'+id).content, true);
};
util.js
<template id=t>
<div class=greeting>
Hello World!
</div>
</template>
<script>
(function() {
var ctx = new Context();
document.body.appendChild(ctx. import('t'));
})();
</script>
bit.ly/zf-import-context
import.html
Custom Elements
● Oddly uncontentious
● Only talking about creating new elements,
not subclassing existing elements.
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function() {
this.textContent = 'Hello World!';
};
proto.addMoreText = function(s) {
this.textContent = this.textContent + s;
};
document.registerElement('hello-element', {
prototype: proto
});
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function() {
this.textContent = 'Hello World!';
};
proto.addMoreText = function(s) {
this.textContent = this.textContent + s;
};
document.registerElement('hello-element', {
prototype: proto
});
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function() {
this.textContent = 'Hello World!';
};
proto.addMoreText = function(s) {
this.textContent = this.textContent + s;
};
document.registerElement('hello-element', {
prototype: proto
});
Custom Element Lifecycle Callbacks
createdCallback
attachedCallback
detachedCallback
attributeChangedCallback
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function() {
this.textContent = 'Hello World!';
};
proto.addMoreText = function(s) {
this.textContent = this.textContent + s;
};
document.registerElement('hello-element', {
prototype: proto
});
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function() {
this.textContent = 'Hello World!';
};
proto.addMoreText = function(s) {
this.textContent = this.textContent + s;
};
document.registerElement('hello-element', {
prototype: proto
});
<html>
<body>
<hello-element></hello-element>
</body>
</html>
bit.ly/zf-custom-element
Context = function() {
this.doc = (document.currentScript ||document._currentScript).ownerDocument;
};
Context.prototype. import = function(id) {
return document.importNode(this.doc.querySelector( '#'+id).content, true);
};
function newElement(name, proto) {
var ep = Object.create(HTMLElement.prototype);
Object.keys(proto).forEach( function(key) {
ep[key] = proto[key];
});
document.registerElement(name, {prototype : ep});
}
util.js
Context = function() {
this.doc = (document.currentScript||document._currentScript).ownerDocument;
};
Context.prototype. import = function(id) {
return document.importNode( this.doc.querySelector('#'+id).content, true);
};
function newElement(name, proto) {
var ep = Object.create(HTMLElement.prototype);
Object.keys(proto).forEach(function(key) {
ep[key] = proto[key];
});
document.registerElement(name, {prototype: ep});
}
util.js
newElement('hello-element', {
createdCallback: function() {
this.textContent = 'Hello World!';
},
addMoreText: function(s) {
this.textContent = this.textContent + s;
},
});
bit.ly/zf-newelement
Putting it all together
A motivating example
<template id=t>
<button>Hide</button>
</template>
<script>
(function() {
var ctx = new Context();
newElement('toggle-next', {
createdCallback: function() {
this.appendChild(ctx.import('t'));
this.button = this.querySelector('button');
this.button.addEventListener('click',
this._buttonClick.bind(this));
},
_buttonClick: function() {
var current = this.nextElementSibling.style.visibility;
if (current == 'collapse') {
this.nextElementSibling.style.visibility= 'visible';
this.button.innerText = 'Hide';
} else {
this.nextElementSibling.style.visibility= 'collapse';
this.button.innerText = 'Show';
}
}
})
})();
</script>
<template id=t>
<button>Hide</button>
</template>
<script>
(function() {
var ctx = new Context();
newElement('toggle-next', {
createdCallback: function() {
this.appendChild(ctx.import('t'));
this.button = this.querySelector('button');
this.button.addEventListener('click',
this._buttonClick.bind(this));
},
_buttonClick: function() {
var current = this.nextElementSibling.style.visibility;
if (current == 'collapse') {
this.nextElementSibling.style.visibility = 'visible';
this.button.innerText = 'Hide';
} else {
this.nextElementSibling.style.visibility = 'collapse';
this.button.innerText = 'Show';
}
}
})
})();
</script>
<template id=t>
<button>Hide</button>
</template>
<script>
(function() {
var ctx = new Context();
newElement('toggle-next', {
createdCallback: function() {
this.appendChild(ctx.import('t'));
this.button = this.querySelector('button');
this.button.addEventListener('click',
this._buttonClick.bind(this));
},
_buttonClick: function() {
var current = this.nextElementSibling.style.visibility;
if (current == 'collapse') {
this.nextElementSibling.style.visibility= 'visible';
this.button.innerText = 'Hide';
} else {
this.nextElementSibling.style.visibility= 'collapse';
this.button.innerText = 'Show';
}
}
})
})();
</script>
<template id=t>
<button>Hide</button>
</template>
<script>
(function() {
var ctx = new Context();
newElement('toggle-next', {
createdCallback: function() {
this.appendChild(ctx.import('t'));
this.button = this.querySelector('button');
this.button.addEventListener('click',
this._buttonClick.bind(this));
},
_buttonClick: function() {
var current = this.nextElementSibling.style.visibility;
if (current == 'collapse') {
this.nextElementSibling.style.visibility = 'visible';
this.button.innerText = 'Hide';
} else {
this.nextElementSibling.style.visibility = 'collapse';
this.button.innerText = 'Show';
}
}
})
})();
</script>
<template id=t>
<button>Hide</button>
</template>
<script>
(function() {
var ctx = new Context();
newElement('toggle-next', {
createdCallback: function() {
this.appendChild(ctx.import('t'));
this.button = this.querySelector('button');
this.button.addEventListener('click',
this._buttonClick.bind(this));
},
_buttonClick: function() {
var current = this.nextElementSibling.style.visibility;
if (current == 'collapse') {
this.nextElementSibling.style.visibility= 'visible';
this.button.innerText = 'Hide';
} else {
this.nextElementSibling.style.visibility= 'collapse';
this.button.innerText = 'Show';
}
}
})
})();
</script>
<template id=t>
<button>Hide</button>
</template>
<script>
(function() {
var ctx = new Context();
NewElement('toggle-next', {
createdCallback: function() {
this.appendChild(ctx.import('t'));
this.button = this.querySelector('button');
this.button.addEventListener('click',
this._buttonClick.bind(this));
},
_buttonClick: function() {
var current = this.nextElementSibling.style.visibility;
if (current == 'collapse') {
this.nextElementSibling.style.visibility = 'visible';
this.button.innerText = 'Hide';
} else {
this.nextElementSibling.style.visibility = 'collapse';
this.button.innerText = 'Show';
}
}
})
})();
</script>
<template id=t>
<button>Hide</button>
</template>
<script>
(function() {
var ctx = new Context();
newElement('toggle-next', {
createdCallback: function() {
this.appendChild(ctx.import('t'));
this.button = this.querySelector('button');
this.button.addEventListener('click',
this._buttonClick.bind(this));
},
_buttonClick: function() {
var current = this.nextElementSibling.style.visibility;
if (current == 'collapse') {
this.nextElementSibling.style.visibility= 'visible';
this.button.innerText = 'Hide';
} else {
this.nextElementSibling.style.visibility= 'collapse';
this.button.innerText = 'Show';
}
}
})
})();
</script>
<!DOCTYPE html>
<html>
<head>
<script src="webcomponents.js"></script>
<script src="util.js"></script>
<link rel="import" href="toggle.html">
</head>
<body>
<toggle-next></toggle-next>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi dignissim,
nisi non rhoncus condimentum, felis ante porta eros, ut tincidunt odio nisl
a libero.
</p>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<script src="webcomponents.js"></script>
<script src="util.js"></script>
<link rel="import" href="toggle.html">
</head>
<body>
<toggle-next></toggle-next>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi dignissim,
nisi non rhoncus condimentum, felis ante porta eros, ut tincidunt odio nisl
a libero.
</p>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<script src="webcomponents.js"></script>
<script src="util.js"></script>
<link rel="import" href="toggle.html">
</head>
<body>
<toggle-next></toggle-next>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi dignissim,
nisi non rhoncus condimentum, felis ante porta eros, ut tincidunt odio nisl
a libero.
</p>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<script src="webcomponents.js"></script>
<script src="util.js"></script>
<link rel="import" href="toggle.html">
</head>
<body>
<toggle-next></toggle-next>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi dignissim,
nisi non rhoncus condimentum, felis ante porta eros, ut tincidunt odio nisl
a libero.
</p>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<script src="webcomponents.js"></script>
<script src="util.js"></script>
<link rel="import" href="toggle.html">
</head>
<body>
<toggle-next></toggle-next>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi dignissim,
nisi non rhoncus condimentum, felis ante porta eros, ut tincidunt odio nisl
a libero.
</p>
</body>
</html>
bit.ly/zf-toggle
So how did this work?
Adjacency in the DOM tree.
Framework
Polyfills
Web
Components
Fill in the
potholes.
Code organization
Organizing around the surfaces already present
in the browser.
● Attributes
● Events
● DOM Structure
<button id=submit>Submit</button>
document.querySelector('#submit').id
document.querySelector('#submit').click()
Attributes
<button id=submit>Submit</button>
document.querySelector('#submit').id
document.querySelector('#submit').click()
Attributes
<button id=submit>Submit</button>
document.querySelector('#submit').id
document.querySelector('#submit').click()
Attributes
<button id=submit>Submit</button>
document.querySelector('#submit').id
document.querySelector('#submit').click()
Attributes
ele.addEventListener('some-event', function(e) { /* */ });
var e = new CustomEvent('some-event', {details: details});
this.dispatchEvent(e);
Events
ele.addEventListener('some-event', function(e) { /* */ });
var e = new CustomEvent('some-event', {details: details});
this.dispatchEvent(e);
Events
ele.addEventListener('some-event', function(e) { /* */ });
var e = new CustomEvent('some-event', {details: details});
this.dispatchEvent(e);
Events
<button>
<img src="">
</button>
<div>
<p class=foo></p>
<p class=foo></p>
<p class=foo></p>
<p class=bar></p>
</div>
DOM Structure
<button>
<img src=""> Parent/Child
</button>
<div>
<p class=foo></p>
<p class=foo></p>
<p class=foo></p>
<p class=bar></p>
</div>
DOM Structure
<button>
<img src="">
</button>
<div>
<p class=foo></p>
<p class=foo></p> CSS Selectors
<p class=foo></p> querySelector('.foo')
<p class=bar></p>
</div>
DOM Structure
A more detailed example
<sort-stuff data-target="#sortable">
<button data-key=pop>Sort on Population</button>
<button data-key=density>Sort on Density</button>
<button data-key=change>Sort on % Change</button>
</sort-stuff>
<ul id=sortable>
<li data-pop=8.4 data-density=27000 data-change=3.86>New York</li>
<li data-pop=3.9 data-density=8092 data-change=3.59>Los Angeles</li>
<li data-pop=2.7 data-density=11842 data-change=0.99>Chicago</li>
<li data-pop=2.2 data-density=3501 data-change=6.63>Houston</li>
<li data-pop=1.5 data-density=11379 data-change=2.25>Philadelphia</li>
</ul>
<sort-stuff data-target="#sortable">
<button data-key=pop>Sort on Population</button>
<button data-key=density>Sort on Density</button>
<button data-key=change>Sort on % Change</button>
</sort-stuff>
<ul id=sortable>
<li data-pop=8.4 data-density=27000 data-change=3.86>New York</li>
<li data-pop=3.9 data-density=8092 data-change=3.59>Los Angeles</li>
<li data-pop=2.7 data-density=11842 data-change=0.99>Chicago</li>
<li data-pop=2.2 data-density=3501 data-change=6.63>Houston</li>
<li data-pop=1.5 data-density=11379 data-change=2.25>Philadelphia</li>
</ul>
<sort-stuff data-target="#sortable">
<button data-key=pop>Sort on Population</button>
<button data-key=density>Sort on Density</button>
<button data-key=change>Sort on % Change</button>
</sort-stuff>
<ul id=sortable>
<li data-pop=8.4 data-density=27000 data-change=3.86>New York</li>
<li data-pop=3.9 data-density=8092 data-change=3.59>Los Angeles</li>
<li data-pop=2.7 data-density=11842 data-change=0.99>Chicago</li>
<li data-pop=2.2 data-density=3501 data-change=6.63>Houston</li>
<li data-pop=1.5 data-density=11379 data-change=2.25>Philadelphia</li>
</ul>
<sort-stuff data-target="#sortable">
<button data-key=pop>Sort on Population</button>
<button data-key=density>Sort on Density</button>
<button data-key=change>Sort on % Change</button>
</sort-stuff>
<ul id=sortable>
<li data-pop=8.4 data-density=27000 data-change=3.86>New York</li>
<li data-pop=3.9 data-density=8092 data-change=3.59>Los Angeles</li>
<li data-pop=2.7 data-density=11842 data-change=0.99>Chicago</li>
<li data-pop=2.2 data-density=3501 data-change=6.63>Houston</li>
<li data-pop=1.5 data-density=11379 data-change=2.25>Philadelphia</li>
</ul>
<sort-stuff data-target="#sortable">
<button data-key=pop>Sort on Population</button>
<button data-key=density>Sort on Density</button>
<button data-key=change>Sort on % Change</button>
</sort-stuff>
<ul id=sortable>
<li data-pop=8.4 data-density=27000 data-change=3.86>New York</li>
<li data-pop=3.9 data-density=8092 data-change=3.59>Los Angeles</li>
<li data-pop=2.7 data-density=11842 data-change=0.99>Chicago</li>
<li data-pop=2.2 data-density=3501 data-change=6.63>Houston</li>
<li data-pop=1.5 data-density=11379 data-change=2.25>Philadelphia</li>
</ul>
newElement('sort-stuff', {
createdCallback : function() {
this.addEventListener( 'click', this._clickHandler.bind( this));
},
_clickHandler : function(e) {
...
},
});
newElement('sort-stuff', {
createdCallback : function() {
this.addEventListener( 'click', this._clickHandler.bind( this));
},
_clickHandler: function(e) {
...
},
});
_clickHandler: function(e) {
var key = e.target.dataset.key;
if (!key) {
return;
}
var target = document.querySelector(this.dataset.target);
var elements = [];
var children = target.children;
for (var i=0; i<children.length; i++) {
var ele = children[i];
elements.push({
value: +ele.dataset[key],
node: ele,
});
}
elements.sort(function(x, y) {
return (x.value == y.value ? 0 : (x.value < y.value ? 1 : -1));
});
elements.forEach(function(i) {
target.appendChild(i.node);
});
},
_clickHandler: function(e) {
var key = e.target.dataset.key;
if (!key) {
return;
}
var target = document.querySelector(this.dataset.target);
var elements = [];
var children = target.children;
for (var i=0; i<children.length; i++) {
var ele = children[i];
elements.push({
value: +ele.dataset[key],
node: ele,
});
}
elements.sort(function(x, y) {
return (x.value == y.value ? 0 : (x.value < y.value ? 1 : -1));
});
elements.forEach(function(i) {
target.appendChild(i.node);
});
},
_clickHandler: function(e) {
var key = e.target.dataset.key;
if (!key) {
return;
}
var target = document.querySelector(this.dataset.target);
var elements = [];
var children = target.children;
for (var i=0; i<children.length; i++) {
var ele = children[i];
elements.push({
value: +ele.dataset[key],
node: ele,
});
}
elements.sort(function(x, y) {
return (x.value == y.value ? 0 : (x.value < y.value ? 1 : -1));
});
elements.forEach(function(i) {
target.appendChild(i.node);
});
},
_clickHandler: function(e) {
var key = e.target.dataset.key;
if (!key) {
return;
}
var target = document.querySelector(this.dataset.target);
var elements = [];
var children = target.children;
for (var i=0; i<children.length; i++) {
var ele = children[i];
elements.push({
value: +ele.dataset[key],
node: ele,
});
}
elements.sort(function(x, y) {
return (x.value == y.value ? 0 : (x.value < y.value ? 1 : -1));
});
elements.forEach(function(i) {
target.appendChild(i.node);
});
},
bit.ly/zf-sort-stuff
● sort-stuff has 'data-target' [Attribute] that selects [DOM Structure] the element
to sort.
● The target children [DOM Structure] have data attributes [Attribute] that
elements are sorted on.
● sort-stuff registers for a 'click' [Events] from its children [DOM Structure].
● sort-stuff children [DOM Structure] have data attributes [Attribute] that
determine how the target children will be sorted.
Surfaces Used
● sort-stuff doesn't care what its children are, only that they generate 'click'
events and the 'click' generating elements have the 'data-key' attributes.
● sort-stuff doesn't care what the elements found at data-target are, only that it
has children that have data-"key" attributes.
Only Surfaces Are Used
● Change the children of <sort-stuff>
● Change the children of sort-stuff.data-target.
Only Surfaces Are Used
<sort-stuff data-target="#sortable">
<p><input type=radio name=sort data-key=pop /> Population</p>
<p><input type=radio name=sort data-key=density /> Density</p>
<p><input type=radio name=sort data-key=change /> % Change</p>
<sort-stuff>
<table>
<tbody id=sortable>
<tr data-pop=8.4 data-density=27000 data-change=3.86><td>New York</td></tr>
<tr data-pop=3.9 data-density=8092 data-change=3.59><td>Los Angeles</td></tr>
<tr data-pop=2.7 data-density=11842 data-change=0.99><td>Chicago</td></tr>
<tr data-pop=2.2 data-density=3501 data-change=6.63><td>Houston</td></tr>
<tr data-pop=1.5 data-density=11379 data-change=2.25><td>Philadelphia</td></tr>
</tbody>
</table>
bit.ly/zf-sort-stuff-2
Roll in toggle-next
bit.ly/sort-stuff-3
Framework
Polyfills
Web
Components
Packaging: HTML Imports
Organization:
Events
Attributes
DOM Structure
Summary
Start writing reusable orthogonally composable
units of HTML+CSS+JS
http://bit.ly/100-line-template
Data Binding
<template id=t>
<div>
<p><a href="{{ url }}">{{ foo.bar.baz }} {{ quux }}</a>!</p>
<!--
Loop over arrays. Use data attributes of data-repeat-[name]="{{ x.y.z }}"
and reference the values iterated over using {{ [name] }}.
For arrays the 'i' state variable is also set.
-->
<ul data-repeat-num="{{ list }}">
<li>{{ num }} {{ i }}</li>
</ul>
<!--
Loop over Objects. For objects the 'key' state variable is also set.
-->
<ul data-repeat-o="{{ anobj }}">
<li>{{ key }}={{ o.name }}</li>
</ul>
</div>
</template>
var clone = ctx.import('t');
Expand(clone, data);
document.body.appendChild(clone);
Extra Benefits
● Enabling mix and match (our use of D3.js).
● Better than native. (support and styling).
○ Ever tried to style a checkbox?
○ details/summary
■ http://caniuse.com/#feat=details
Missing Pieces
● CSS Variables for Shadow DOM
● Better Compilers
There are dozens of us!
● You (probably) don't need a JavaScript framework
https://slack-files.com/T03JT4FC2-F151AAF7A-13fe6f98da
fin
Appendix
● http://webcomponents.org/polyfills/
○ You only need webcomponents-lite.js for all the content in this slide
deck.
● http://bitworking.org/news/2014/05/zero_framework_manifesto
○ The rant that launched it all.
● http://vanilla-js.com/
But what about React Native?
“learn once, write anywhere.“
https://en.wikipedia.org/wiki/List_of_platform-independent_GUI_libraries

Mais conteúdo relacionado

Mais procurados

J Query(04 12 2008) Foiaz
J Query(04 12 2008) FoiazJ Query(04 12 2008) Foiaz
J Query(04 12 2008) Foiaz
testingphase
 

Mais procurados (20)

Web 2.0 And Ajax
Web 2.0 And AjaxWeb 2.0 And Ajax
Web 2.0 And Ajax
 
Web Components for Java Developers
Web Components for Java DevelopersWeb Components for Java Developers
Web Components for Java Developers
 
React native: building native iOS apps with javascript
React native: building native iOS apps with javascriptReact native: building native iOS apps with javascript
React native: building native iOS apps with javascript
 
GQuery a jQuery clone for Gwt, RivieraDev 2011
GQuery a jQuery clone for Gwt, RivieraDev 2011GQuery a jQuery clone for Gwt, RivieraDev 2011
GQuery a jQuery clone for Gwt, RivieraDev 2011
 
Custom Elements with Polymer Web Components #econfpsu16
Custom Elements with Polymer Web Components #econfpsu16Custom Elements with Polymer Web Components #econfpsu16
Custom Elements with Polymer Web Components #econfpsu16
 
Web Components Everywhere
Web Components EverywhereWeb Components Everywhere
Web Components Everywhere
 
Java script
Java scriptJava script
Java script
 
Rock GWT UI's with Polymer Elements
Rock GWT UI's with Polymer ElementsRock GWT UI's with Polymer Elements
Rock GWT UI's with Polymer Elements
 
Introduction to java_script
Introduction to java_scriptIntroduction to java_script
Introduction to java_script
 
Google Devfest Singapore - OpenSocial
Google Devfest Singapore - OpenSocialGoogle Devfest Singapore - OpenSocial
Google Devfest Singapore - OpenSocial
 
The Complementarity of React and Web Components
The Complementarity of React and Web ComponentsThe Complementarity of React and Web Components
The Complementarity of React and Web Components
 
J Query(04 12 2008) Foiaz
J Query(04 12 2008) FoiazJ Query(04 12 2008) Foiaz
J Query(04 12 2008) Foiaz
 
React JS Belgium Touch Base - React, Flux, React Native
React JS Belgium Touch Base - React, Flux, React NativeReact JS Belgium Touch Base - React, Flux, React Native
React JS Belgium Touch Base - React, Flux, React Native
 
Client Side rendering Not so Easy
Client Side rendering Not so EasyClient Side rendering Not so Easy
Client Side rendering Not so Easy
 
Dive into AngularJS and directives
Dive into AngularJS and directivesDive into AngularJS and directives
Dive into AngularJS and directives
 
Polymer, A Web Component Polyfill Library
Polymer, A Web Component Polyfill LibraryPolymer, A Web Component Polyfill Library
Polymer, A Web Component Polyfill Library
 
Java script
Java scriptJava script
Java script
 
Intro to Web Components, Polymer & Vaadin Elements
Intro to Web Components, Polymer & Vaadin ElementsIntro to Web Components, Polymer & Vaadin Elements
Intro to Web Components, Polymer & Vaadin Elements
 
JAVA SCRIPT
JAVA SCRIPTJAVA SCRIPT
JAVA SCRIPT
 
AngularJs Crash Course
AngularJs Crash CourseAngularJs Crash Course
AngularJs Crash Course
 

Semelhante a 2016 stop writing javascript frameworks by Joe Gregorio

Semelhante a 2016 stop writing javascript frameworks by Joe Gregorio (20)

PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...
PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...
PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...
 
ENIB 2015-2016 - CAI Web - S01E01- Côté navigateur 3/3 - Web components avec ...
ENIB 2015-2016 - CAI Web - S01E01- Côté navigateur 3/3 - Web components avec ...ENIB 2015-2016 - CAI Web - S01E01- Côté navigateur 3/3 - Web components avec ...
ENIB 2015-2016 - CAI Web - S01E01- Côté navigateur 3/3 - Web components avec ...
 
ENIB 2015 2016 - CAI Web S02E01- Côté Navigateur 3/3 - Web Components avec Po...
ENIB 2015 2016 - CAI Web S02E01- Côté Navigateur 3/3 - Web Components avec Po...ENIB 2015 2016 - CAI Web S02E01- Côté Navigateur 3/3 - Web Components avec Po...
ENIB 2015 2016 - CAI Web S02E01- Côté Navigateur 3/3 - Web Components avec Po...
 
Neoito — How modern browsers work
Neoito — How modern browsers workNeoito — How modern browsers work
Neoito — How modern browsers work
 
HTML, CSS & Javascript Architecture (extended version) - Jan Kraus
HTML, CSS & Javascript Architecture (extended version) - Jan KrausHTML, CSS & Javascript Architecture (extended version) - Jan Kraus
HTML, CSS & Javascript Architecture (extended version) - Jan Kraus
 
JavascriptMVC: Another choice of web framework
JavascriptMVC: Another choice of web frameworkJavascriptMVC: Another choice of web framework
JavascriptMVC: Another choice of web framework
 
Web components
Web componentsWeb components
Web components
 
Developing a Joomla 3.x Component using RAD FOF- Part 2: Front-end + demo - J...
Developing a Joomla 3.x Component using RAD FOF- Part 2: Front-end + demo - J...Developing a Joomla 3.x Component using RAD FOF- Part 2: Front-end + demo - J...
Developing a Joomla 3.x Component using RAD FOF- Part 2: Front-end + demo - J...
 
Architektura html, css i javascript - Jan Kraus
Architektura html, css i javascript - Jan KrausArchitektura html, css i javascript - Jan Kraus
Architektura html, css i javascript - Jan Kraus
 
Dust.js
Dust.jsDust.js
Dust.js
 
Web components. Compose the web.
Web components. Compose the web.Web components. Compose the web.
Web components. Compose the web.
 
Web Components v1
Web Components v1Web Components v1
Web Components v1
 
Build Reusable Web Components using HTML5 Web cComponents
Build Reusable Web Components using HTML5 Web cComponentsBuild Reusable Web Components using HTML5 Web cComponents
Build Reusable Web Components using HTML5 Web cComponents
 
Angular.js for beginners
Angular.js for beginners Angular.js for beginners
Angular.js for beginners
 
Performance (browser)
Performance (browser)Performance (browser)
Performance (browser)
 
Modern frontend development with VueJs
Modern frontend development with VueJsModern frontend development with VueJs
Modern frontend development with VueJs
 
Migrations
MigrationsMigrations
Migrations
 
Iteria lowcode 2022-01-10
Iteria lowcode 2022-01-10Iteria lowcode 2022-01-10
Iteria lowcode 2022-01-10
 
Flash develop presentation
Flash develop presentationFlash develop presentation
Flash develop presentation
 
Hands on react native
Hands on react nativeHands on react native
Hands on react native
 

Mais de David Zapateria Besteiro

Mais de David Zapateria Besteiro (6)

Javascript - Módulo 9: Geolocalización en HTML5, Google maps, y SVG
Javascript - Módulo 9: Geolocalización en HTML5, Google maps, y SVGJavascript - Módulo 9: Geolocalización en HTML5, Google maps, y SVG
Javascript - Módulo 9: Geolocalización en HTML5, Google maps, y SVG
 
Javascript - Módulo 8: LocalStorage, iFrames, Origin policy y JSON
Javascript - Módulo 8: LocalStorage, iFrames, Origin policy y JSONJavascript - Módulo 8: LocalStorage, iFrames, Origin policy y JSON
Javascript - Módulo 8: LocalStorage, iFrames, Origin policy y JSON
 
Javascript Módulo 7 - PROFUNDIZACIÓN EN ARRAYS, OBJETOS, PROPIEDADES, MÉTODOS...
Javascript Módulo 7 - PROFUNDIZACIÓN EN ARRAYS, OBJETOS, PROPIEDADES, MÉTODOS...Javascript Módulo 7 - PROFUNDIZACIÓN EN ARRAYS, OBJETOS, PROPIEDADES, MÉTODOS...
Javascript Módulo 7 - PROFUNDIZACIÓN EN ARRAYS, OBJETOS, PROPIEDADES, MÉTODOS...
 
Javascript Módulo 5 - Bucles, Arrays. Funciones como objectos. Ámbitos. Cierr...
Javascript Módulo 5 - Bucles, Arrays. Funciones como objectos. Ámbitos. Cierr...Javascript Módulo 5 - Bucles, Arrays. Funciones como objectos. Ámbitos. Cierr...
Javascript Módulo 5 - Bucles, Arrays. Funciones como objectos. Ámbitos. Cierr...
 
Javascript - Módulo 4: Booleano, if/else, string, número, DOM, eventos e inte...
Javascript - Módulo 4: Booleano, if/else, string, número, DOM, eventos e inte...Javascript - Módulo 4: Booleano, if/else, string, número, DOM, eventos e inte...
Javascript - Módulo 4: Booleano, if/else, string, número, DOM, eventos e inte...
 
Javascript Módulo 5 - javascript sentencia, expresión, variable, función - Un...
Javascript Módulo 5 - javascript sentencia, expresión, variable, función - Un...Javascript Módulo 5 - javascript sentencia, expresión, variable, función - Un...
Javascript Módulo 5 - javascript sentencia, expresión, variable, función - Un...
 

Último

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Último (20)

From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 

2016 stop writing javascript frameworks by Joe Gregorio