web uis paradigma novo para componentes: um...

44
PENSANDO EM COMPONENTES: UM PARADIGMA NOVO PARA WEB UIS

Upload: others

Post on 30-Apr-2020

4 views

Category:

Documents


0 download

TRANSCRIPT

Oliver Häger

1. Introdução Uma (ultra-)breve História do Tempo

Intr

oduç

ão

Intr

oduç

ão

<form name="person-editor" > <h2>Person Editor</h2>

<label for="firstName">First Name</label> <input id="firstName" class="form-control" type="text" onchange="changed(event)"/>

<label for="lastName">Last Name</label> <input id="lastName" class="form-control" type="text" onchange="changed(event)"/>

<!-- ... -->

<button type="button" class="btn btn-success" onclick="save(event)">Save</button></form>

personeditor.html

Van

illa

JS

var httpRequest = new XMLHttpRequest() ;var person = {};

function changed(event){ person[event. target.id] = event.target.value;}

function save(){ httpRequest.onreadystatechange = function(){/* ... */}; httpRequest.open("POST", "http://www.neolithic.com/person" ); httpRequest.setRequestHeader ('Content-Type' , 'application/json' ); httpRequest.send( JSON.stringify(person) );}

personeditor.js

Van

illa

JS

<head> <script src="js/lib/jquery.js" ></script> <script src="js/person.editor.plugin.js" ></script></head><body><div id="person-editor" ></div><script> (function(){ function save(data){ // ... send to server }

$('#person-editor' ).personEditor(save); })();</script></body>

personeditor.html

jQue

ry P

lugi

n

function PersonEditor(saveCallback){

var _personData = {};

this.render = function(target){ var form = document.createElement('form');

// create elements here ...

saveButton.addEventListener('click', function(event){ saveCallback(_personData); }); form.appendChild(inputFirstName); form.appendChild(inputLastName); form.appendChild(saveButton); target.appendChild(form); }}

(function($){ $.fn.personEditor = function(saveCallback){ this.each( function() { var editor = new PersonEditor(saveCallback); editor.render(this); }); };})(jQuery);

personeditor.plugin.js

jQue

ry P

lugi

n

Ang

ular

JS

<form name="person-editor" ng-controller="personeditorController" ><h2>Person Editor</h2>

<label for="firstName">First Name</label><input id="firstName" class="form-control" type="text" ng-model="

person.firstName" />

<label for="lastName">Last Name</label><input id="lastName" class="form-control" type="text" ng-model="

person.lastName" /> <!-- ... -->

<button type="button" class="btn btn-success" ng-click="save($event)">Save</button></form>

personeditor.html

app.controller("personeditorController" , function($scope, $http){

$scope.person = {};

$scope.save = function(event){

var req = { method: 'POST', url: 'http://example.com/api/v1/person' , headers: { 'Content-Type' : 'application/json' }, data: $scope.person };

$http(req).then(function(){ // handle response }, console.error);

}});

personeditor.controller.js

Ang

ular

JS

2. Componentes O novo paradigma

Com

pone

ntes

Com

pone

ntes

Com

pone

ntes

combinável

reutilizável

Com

pone

ntes

<div class="container"><editor-frame title="Person" onsave="savePerson">

<person-editor></person-editor> </editor-frame>

<editor-frame title="Product" onsave="saveProduct"> <product-editor></product-editor>

</editor-frame></div>A

ngul

ar D

irec

tive

s

<h2>{{title}}</h2><div class="form-group" ng-transclude></div><button class="btn btn-success" ng-click="requestSave(editorModel)">Save</button>

editorframe.html

Ang

ular

Dir

ecti

ves

angular.module('app.components.editorframe' , []) .directive('editorFrame', function() { return { templateUrl: 'components/ng/editorframe.html' , transclude: true, scope : { title : '@', onsave : '=' }, controller : function($scope){ $scope. editorModel = {};

this.updateModel = function(model){ $scope. editorModel = model; };

$scope.requestSave = function(editorModel) { $scope. onsave(editorModel); }; } }; });

editorframe-component.js

Ang

ular

Dir

ecti

ves

<div class="row"> <div class="col-lg-6 col-sm-6" > <label> First Name</label> <input class="form-control" type="text" ng-change="changed()" ng-model="person.firstName" /> </div> <div class="col-lg-6 col-sm-6" > <label> Last Name</label> <input class="form-control" type="text" ng-change="changed()" ng-model="person.lastName" /> </div> <div class="col-lg-6 col-sm-6" > <label> E-Mail</label> <input class="form-control" type="email" ng-change="changed()" ng-model="person.email" /> </div></div>

person-editor-component.html

Ang

ular

Dir

ecti

ves

angular.module('app.components.personeditor' , ['app.components.editorframe'])

.directive('personEditor' , function($rootScope) { return { require : "^editorFrame" , restrict : "AE", scope : { }, templateUrl: 'components/ng/person-editor-directive.html' , link : function($scope, element, attrs, frameCtrl) { $scope. changed = function(){ frameCtrl. updateModel($scope.person); } } }; });

person-editor-component.js

Ang

ular

Dir

ecti

ves

Bibliotéca para ViewPerformático

Sem dependências

Facebook (e Instagram)

Rea

ctJS

Mostrar custom elementvar ReactApp = React. createClass({

saveCustomer: function(customer) { /* ... */ }, saveProduct: function(product){ /* ... */ }, render: function () {

return ( <div> <EditorFrame title="Customer Editor" onSave={this.saveCustomer}> <CustomerEditor/> </EditorFrame> <EditorFrame title="Product Editor" onSave={this.saveProduct}> <ProductEditor/> </EditorFrame> </div> ) }})

react-app.jsx

Rea

ctJS

Mostrar custom elementvar EditorFrame = React.createClass( { propTypes: { title: React.PropTypes.string.isRequired, onSave: React.PropTypes.func.isRequired },

getInitialState : function(){ return {data : {}}; }, change : function(data){ this.state.data = data; }, onSave: function (event) { this.props.onSave(this.state.data); },

render: function () { // intercept the change callback this.props.children.props.onChange = this.change;

return ( <div className="panel"> <h3 className="panel-title">{this.props.title}</h3> <div className="panel-body"> {this.props.children} <hr/> <button className="btn" onClick={this.onSave}>Save</button> </div> </div> ) } });

editor-frame.jsx

Rea

ctJS

Mostrar custom elementvar CustomerEditor = React.createClass({

PropTypes: { onChange : React.PropTypes.func.isRequired },

getInitialState : function(){ return {data: {}}; },

editorDataChanged: function (event) { this.state.data[event.target.name] = event.target.value; this.props.onChange(this.state.data); // propagate data model },

render: function () { return ( <div> <div className="form-group"> <input name="name" className="form-control" type="text" onChange={this.editorDataChanged}/> </div> <div className="form-group"> <input name="email" className="form-control" type="text" onChange={this.editorDataChanged}/> </div> </div> ) }});

customer-editor.jsx

Rea

ctJS

Bibliotéca para View

Criado em cima da especificação Web Components

Google

Catálogo de componentes tipo Material Design

Poly

mer

Mostrar custom element

<section data-route="editor"><paper-material elevation="1">

<editor-frame title="Person Editor" > <editor-content-person/>

</editor-frame></paper-material><paper-material elevation="1">

<editor-frame title="Address Editor" ><editor-content-address/>

</editor-frame></paper-material>

</section>

index.html

Poly

mer

Mostrar custom element<link rel="import" href="/bower_components/paper-button/paper-button.html" ><link rel="import" href="../common/message-dialog.html" >

<dom-module id="editor-frame" > <style> :host { display: block; } .button { margin-top: 1em; } @media (max-width: 600px) { h1.paper-font-display1 { font-size: 24px; } } </style>

<template><!-- part 2 -->

</template>

<script><!-- part 3 -->

</script></dom-module>

editor-frame.html (1/3)

Poly

mer

Mostrar custom element<link rel="import" href="/bower_components/paper-button/paper-button.html" ><link rel="import" href="../common/message-dialog.html" >

<dom-module id="editor-frame" > <style>

<!-- part 1 --> </style>

<template> <h1 class="paper-font-display1" ><span>{{title}}</span></h1>

<div id="content"> <content></content> </div>

<paper-button class="button" on-click="save" raised>Save</paper-button> <message-dialog id="dialog" title="Saved Data" message="[[editorData]]"></message-dialog> </template>

<script><!-- part 3 -->

</script></dom-module>

editor-frame.html (2/3)

Poly

mer

Mostrar custom element <script>(function () { Polymer({ is: 'editor-frame' ,

properties: { editorData: String, title: { type: String, notify: true } },

ready: function() {this.addEventListener ('changed-model' , this.updateModel);

},updateModel : function(event){ this.editorData = JSON.stringify(event.detail.model);},save: function () { this.$.dialog.open();}

});})();

</script>

editor-frame.html (3/3)

Poly

mer

Mostrar custom element<link rel="import" href="/bower_components/paper-input/paper-input.html" ><link rel="import" href="editor-content-behaviour.html" >

<dom-module id="editor-content-person" > <style>

<!-- encapsulated style --> </style>

<template> <paper-input class="width-50" name="firstName" label="First Name" on-change="handleChange" ></paper-input> <paper-input class="width-50" name="lastName" label="Last Name" on-change="handleChange" ></paper-input> </template>

<script> (function () { "use strict";

Polymer({ is: 'editor-content-person' ,

behaviors : [EditorContentBehavior ] });

})();</script>

</dom-module>

editor-content-person.html

Poly

mer

Mostrar custom element

<script> EditorContentBehavior = {

properties: { model : { type: Object, value : function () { return {}; } // not shared among instances } },

handleChange : function(e){ this.model[e.target.name] = e.target.value; this.fire('changed-model' , {model : this.model}); } };</script>

editor-content-behavior.html

Poly

mer

3. Componentização Novos mundos

Com

pone

ntiz

ação

EncapsulamentoDOM

CSSJavascript

Lifecycle

Virtual DOMShadow (Shady) DOM

Scoped Styles

Dados CompartilhadosInstâncias

Pensar em componentes

Fluxo de dados

Arquitetura

Des

afio

s

Reusabilidade

ManutenibilidadeRobustez

Produtividade

Gan

hos

Crescimento descontrolado

Black Box

Desenvolvimento Inicial

Ris

cos

3. Outlook The next big thing?

Specificação W3C Conjunto de 4 Sub-Specificações

TemplatesImports

Custom ElementsShadow DOM

Web

Com

pone

nts

#document-fragment

<my-awesome-element/>

<link rel=”import”/><template/>

Web

Com

pone

nts

Templates

Imports

Custom Elements

Shadow DOM

Ang

ular

2.0

<html><head> <title>Angular 2 Quickstart </title> <script src="https://github.jspm.io/jmcriffey/[email protected]/traceur-runtime.js" ></script> <script src="https://jspm.io/[email protected]" ></script> <script src="https://code.angularjs.org/2.0.0-alpha.28/angular2.dev.js"></script></head><body> <!-- The app component --> <my-app></my-app> <script>System.import( 'app');</script></body></html>

Ang

ular

2.0

@Component({ selector: 'my-app'})@View({ template: '<h1>Hello {{ name }}</h1>'})

// Component controllerclass MyAppComponent { name: string; constructor() { this.name = 'Alice'; }}

bootstrap(MyAppComponent) ;

AuraJSAurelia

FlightJSMithrilJSSkateJS

...

Out

ros

[email protected]@dextra-sw.com

https://br.linkedin.com/in/oliverhager

Thnx!Questions!