Anúncio
Anúncio

Mais conteúdo relacionado

Apresentações para você(20)

Anúncio

Frontin like-a-backer

  1. Frontin' Like A Back-er by @frankdejonge
  2. The PHP League Flysystem
  3. 2 million downloads, thank you!
  4. There's no other option than using JavaScript. - most of my friends
  5. JavaScript is a means to an end. - almost all of my friends
  6. If JavaScript is required, I'll hire somebody. - my friends who have companies
  7. If we hate something, why do we do it?
  8. We all like the result: Snappy UI / UX
  9. I made a server browser do this!
  10. Loving JavaScript Hating JavaScript Dealing with JavaScript
  11. Take a step back. React Reflect
  12. $(window).load(function () { $('a.external-link').on('click', function clickHandler (e) { e.preventDefault(); if (confirm('Really?')) { $(this).off('click', clickHandler).click(); } }); });
  13. This is not separation of concerns. <a class="hide-me">Click and I'll disappear</a> <script type="application/javascript"> $('a.hide_me').on('click', function (e) { e.preventDefault(); $(this).hide(); }); </script> It's error-prone.
  14. Result driven approach. Just enough code to make it work.
  15. Looks good at the front.
  16. Not so pretty at the back.
  17. Not good enough. Doesn't supply what I need.
  18. We need: 1. Generated Elements; Templates? 2. XHR requests; Obviously, it's the future. 3. Data Handling; Models? Collections?
  19. Our saviours: Backbone.js, Ember.js, Angular.js
  20. Backbone.JS: You figure it out. var DocumentRow = Backbone.View.extend({ tagName: "li", className: "document-row", events: { "click .icon": "open", }, initialize: function() { this.listenTo(this.model, "change", this.render); }, render: function() { var idea = 'I have none'; } });
  21. Angular.JS: ng-whatever. <html ng-app="phonecatApp"> <head> <script src="bower_components/angular/angular.js"></script> <script src="js/controllers.js"></script> </head> <body ng-controller="PhoneListCtrl"> <ul> <li ng-repeat="phone in phones"> <span>{{phone.name}}</span> <p>{{phone.snippet}}</p> </li> </ul> </body> </html>
  22. Ember.JS: Handlebars / Mustache. 23 page doc needed to explain views.
  23. You don't like JS and HTML; here's something different.
  24. It just doesn't work.
  25. I'm OUT! Back to HTML.
  26. Back-end flow: Receive HTTP Request. Process & Collect Data. Send Data => Template Engine. Send HTTP Response.
  27. Current Application State in HTML
  28. Declarative <h1 class="hello">Hello World!</h1>   Composable <div class="hello"> <h1 class="hello__message">Hello World!</h1> </div>
  29. State & Behaviour <input type="checkbox" checked/>
  30. Why can't it just be like that? Just the UI Just like HTML
  31. React (JS)
  32. Define var HelloWorld = React.createClass({ render: function () { return <h1>Hello, World!</h1>; } });   Use React.render( <HelloWorld/>, document.getElementById('root') );
  33. HTML in my JS?! What The Fudge!
  34. #ProTip: Get over it.
  35. JSX is just a DSL for HTML in JavaScript
  36. Sugar var HelloWorld = React.createClass({ render: function () { return <h1>Hello, World!<h1>; } });
  37. Desugared var HelloWorld = React.createClass({ render: function () { return React.createElement( 'h1', {className: 'hello_world'}, 'Hello, World!' ); } });
  38. Just like HTML: It's declarative <ModalWindow/>
  39. Just like HTML: You can pass properties <ModalWindow opened={true}/>
  40. Just like HTML: It's composable. <ModalWindow> <ModalHeader title="Hello World"/> <ModalBody> ... </ModalBody> </ModalWindow>
  41. It shows intent. <ProfileEditor> <Username /> <ProfilePicture /> <Biography /> </ProfileEditor>
  42. But where do I put my data? React is all about the bass UI.
  43. What is data in the UI? Properties & State
  44. Properties = External Input
  45. var Badge = React.createClass({ render: function () { return <div className="badge"> <h1>{this.props.name}</h1> <div>; } }); React.render( <Badge name="Kayla" />, document.getElementById('root') );
  46. var Badge = React.createClass({ render: function () { var description = this.props.is_awesome ? 'is awesome!' : 'is not awesome'; return <div className="badge"> <h1>{this.props.text}</h1> <p> {description} </p> <div>; } }); React.render(<Badge name="Kayla" is_awesome={true} />, rootNode);
  47. var BadgeList = React.createClass({ render: function () { var badges = this.props.people.map(function (person) { return <Badge key={person.id} {...person} />; }); return <div className="badge_list">{badges}<div>; } }); React.render(<BadgeList people={peopleCollection} />, rootNode);
  48. State = Internal
  49. var Toggle = React.createClass({ getInitialState: function () { return { completed: false }; }, render: function () { var className = this.state.completed ? 'toggle--completed' : 'toggle'; return <div className={className} />; } });
  50. var Toggle = React.createClass({ getInitialState: function () { return { completed: false }; }, onClick: function () { this.setState({completed: ! this.state.completed}); }, render: function () { var className = this.state.completed ? 'toggle--completed' : 'toggle'; return <div onClick={this.onClick} className={className} />; } });
  51. Nice but what about MY data?
  52. Back-end data flow: 1. Receive an HTTP request. 2. Process + Get relevant data. 3. Respond with a rendered view.
  53. Back-end data flow: 1. Action (intention) 2. Domain (business stuff) 3. Response (json/html/ ... xml?)
  54. How does this map to JavaScript / React?
  55. Front-end data flow: 1. Action (intention) 2. Domain (?) 3. Response (React)
  56. Front-end data flow: 1. Action (intention) 2. Store / Services (data layer) 3. Response (React)
  57. Stores hold the application state.
  58. Services interact with APIs.
  59.  
  60. Flux
  61. Flux is only a pattern There are many implementations already.
  62. Alt.js Actions & Stores
  63. /actions/ /stores/ /components/
  64. /alt.js /actions/TodoActions.js /stores/TodoStore.js /components/TodoApplication.js /components/TodoList.js
  65. import Alt from 'alt'; let alt = new Alt(); export default alt;
  66. // actions/TodoActions.js import alt from '../alt'; class TodoActions { createTodo (task) { this.dispatch({ task }); } } export default alt.createActions(TodoActions);
  67. // stores/TodoStore.js import alt from '../alt'; import TodoActions from '../actions/TodoActions'; class TodoStore { constructor() { this.todos = []; this.bindListeners({ handleCreatedTodo: TodoActions.CREATE_TODO }); } handleCreatedTodo (todo) { this.todos.push(todo); } } export default alt.createStore(TodoStore, 'TodoStore');
  68. import React from 'react'; var TodoApplication = React.createClass({ render() { var todoList = this.state.todos.map(function (todo, index) { return <li key={index}>{todo.task}</li>; }); return <div className="todos"> <ul className="todo__list"> {todoList} </ul> <input type="text"/> </div>; } });
  69. import TodoStore from '../stores/TodoStore'; var TodoApplication = React.createClass({ componentWillMount () { TodoStore.listen(this.handleChange); } componentWillUnmount () { TodoStore.unlisten(this.handleChange); } handleChange (state) { this.setState(state); } getInitialState() { return TodoStore.getState(); } });
  70. var TodoApplication = React.createClass({ render() { var todoList = this.state.todos.map(function (todo, index) { return <li key={index}>{todo.task}</li>; }); return <div className="todos"> <ul className="todo__list"> {todoList} </ul> <input type="text"/> </div>; } });
  71. var TodoList = React.createClass({ render() { var todoList = this.props.todos.map(function (todo, index) { return <li key={index}>{todo.task}</li>; }); return <ul className="todo__list"> {todoList} </ul>; } });
  72. import TodoList from './TodoList'; var TodoApplication = React.createClass({ render() { return <div className="todos"> <TodoList todos={this.state.todos} /> <input type="text"/> </div>; } });
  73. import TodoList from './TodoList'; import TodoActions from '../actions/TodoActions'; var TodoApplication = React.createClass({ handleCreateTodo (event) { if (event.keyCode !== 13) return; var task = event.target.value; TodoAction.createTodo(task); } render() { return <div className="todos"> <TodoList todos={this.state.todos} /> <input type="text" onKeyDown={this.handleCreateTodo}/> </div>; } });
  74. So, what about my Laravel App?
  75. // routes.php $app->post('/todos', function (Request $request) { $todo = $request->json()->all(); // Store the TODO return new JsonResponse($todo->all()); });
  76. import alt from '../alt'; import TodoActions from '../actions/TodoActions'; class TodoStore { handleCreatedTodo (todo) { fetch('/todos', { method: 'post', body: JSON.stringify(todo) }).then((response) => { this.todos.push(response.json()); this.emitChange(); }); } } export default alt.createStore(TodoStore, 'TodoStore');
  77. What do we know so far?
  78. Writing front-end code, like back-end code. It's all about data-flow.
  79. Intent is everything.
  80. Complexity should be facilitated. Choose a tool that supports it.
  81. React can run on the server.
  82. Declarative UI across the board.
  83. Thank you for your time!
Anúncio