Ember: The Magic, Demystified

Ember: The Magic, Demystified

How do the names that you provide to Ember actually end up resulting in Ember looking for a given route/controller/view/template combination? How does this apply to components and their templates? This talk reviews the Ember internals to illuminate that this isn't magical, but quite straight-forward.

0dfd10ad198ae5a87640da046a77a90a?s=128

Robert Jackson

June 17, 2014
Tweet

Transcript

  1. Ember: The Magic, Demystified

  2. Who the heck is this guy? • Ember Core Team

    • General OSS addict • DockYarder twitter: rwjblue github: rjackson
  3. Sweet Ember Shirts

  4. Sweet Ember Shirts

  5. None
  6. Ember: The Magic, Demystified

  7. Magic Naming?

  8. Items to review: • Lookup From Routes to Templates •

    Component Lookup
  9. Route Lookup

  10. Route Lookup • Route • Controller • View • Template

  11. Route Lookup // app/router.js var Router = Ember.Router.extend(); Router.map(function() {

    this.route('posts'); }); export default Router;
  12. Route Lookup {{! /app/templates/posts.hbs }} <h3>Woot!! You found the posts

    route!</h3>
  13. Route Lookup http://locahost:4200/posts How does this:

  14. Route Lookup End up with this?

  15. Route Lookup <script> var Klass = require('sample-app/app')['default']; window.SampleApp = Klass.create();

    </script> Ember.Application.create
  16. Route Lookup this.setupEventDispatcher(); this.ready(); // user hook this.startRouting(); this.resolve(this); Ember.Application#didBecomeReady

  17. Route Lookup this.setupEventDispatcher(); this.ready(); // user hook this.startRouting(); this.resolve(this); Ember.Application#didBecomeReady

  18. Route Lookup this.constructor.map(Ember.K); this._setupRouter(router, location); this.handleURL(‘/posts’); Ember.Router#startRouting

  19. Route Lookup var dsl = DSL.map(function() { this.resource( 'application', {

    path: "/" }, function() { callback.call(this); }); }); Ember.Router.map
  20. Route Lookup var dsl = DSL.map(function() { this.resource( 'application', {

    path: "/" }, function() { callback.call(this); }); }); Ember.Router.map
  21. Route Lookup - Deep Dive Ember.Router#_setupRouter • Sets `router.getHandler` •

    Sets URL update hooks
  22. Route Lookup var R = container.lookupFactory('route:basic') return function(name) { var

    handler = this.container.lookup('route:' + name); handler.routeName = name; if (handler) { return handler;} this.container.register('route:' + name, R.extend()); return this.container.lookup('route:' + name); }; Ember.Router#_getHandlerFunction
  23. Route Lookup • Router.map sets up the handlers • router.js

    handles the actual route transitions • New route is entered: getHandler(‘posts’) • So we have a Route instance, now what?
  24. Route Rendering • router.js invokes various async hooks (activate, model,

    redirect, etc) • router.js invokes route.setup
  25. Route Rendering var controllerName = this.controllerName || this.routeName, controller =

    this.controllerFor(controllerName, true); if (!controller) { controller = this.generateController(controllerName,context); } Ember.Route#setup
  26. Route Rendering this.setupController(controller, context, transition); this.renderTemplate(controller, context); Ember.Route#setup

  27. Route Rendering var name = this.routeName; var templateName = this.templateName

    || name; var viewName = this.viewName || name; Ember.Route#render
  28. Route Rendering var view = container.lookup('view:' + viewName), template =

    view ? view.get('template') : null; if (!template) { template = container.lookup('template:' + templateName); } Ember.Route#render
  29. Route Rendering options = normalizeOptions(this, name, template, options); view =

    setupView(view, container, options); appendView(this, view, options); Ember.Route#render
  30. Route Lookup app/routes/posts.js app/controllers/posts.js app/views/posts.js app/templates/posts.hbs Files looked up:

  31. Route Lookup app/routes/posts.js app/controllers/posts.js app/views/posts.js app/templates/posts.hbs Files looked up:

  32. Route Lookup // packages/ember-routing/lib/system/router.js#L319 // Ember.Router#_getHandlerFunction var handler = this.container.lookup('route:'

    + name); handler.routeName = name; app/routes/posts.js
  33. Route Lookup app/routes/posts.js app/controllers/posts.js app/views/posts.js app/templates/posts.hbs Files looked up:

  34. Route Lookup // packages/ember-routing/lib/system/route.js#L696 // Ember.Route#setup controller = this.controllerFor(controllerName, true);

    if (!controller) { controller = this.generateController(controllerName,context); } app/controllers/posts.js
  35. Route Lookup app/routes/posts.js app/controllers/posts.js app/views/posts.js app/templates/posts.hbs Files looked up:

  36. Route Lookup // packages/ember-routing/lib/system/route.js#L1377 // Ember.Route#render view = container.lookup('view:' +

    viewName), view = setupView(view, container, options); appendView(this, view, options); app/views/posts.js
  37. Route Lookup app/routes/posts.js app/controllers/posts.js app/views/posts.js app/templates/posts.hbs Files looked up:

  38. Route Lookup app/templates/posts.hbs // packages/ember-routing/lib/system/route.js#L1381 // Ember.Route#render template = view

    ? view.get('template') : null; template = template || container.lookup('template:' + templateName); options = normalizeOptions(this, name, template, options); view = setupView(view, container, options);
  39. Component Lookup

  40. Component Lookup • Layout • Component

  41. // app/templates/application.hbs {{x-foo bar="baz"}} // app/templates/components/x-foo.hbs {{foobar}} Component Lookup Templates:

  42. export default Ember.Component.extend({ foobar: Ember.computed('bar', function() { return 'foo' +

    Ember.get(this, 'bar'); }) }); Component Lookup Component: x-foo
  43. var id = new Handlebars.AST.IdNode([{ part: '_triageMustache' }]); mustache =

    new Handlebars.AST.MustacheNode( [id].concat([mustache.id]), mustache.hash, !mustache.escaped ); return Handlebars.Compiler.prototype.mustache.call(this, mustache); Component Lookup Ember.Handlebars.Compiler.mustache
  44. var helper = EmberHandlebars.resolveHelper( options.data.view.container, property ); if (helper) {

    return helper.call(this, options); } Component Lookup _triageMustacheHelper
  45. var componentLookup = container.lookup('component-lookup:main'); var Component = componentLookup.lookupFactory(name, container); if

    (Component) { helper = EmberHandlebars.makeViewHelper(Component); container.register('helper:' + name, helper); } Component Lookup resolveHelper
  46. Component Lookup Em.ComponentLookup.lookupFactory var fullName = 'component:' + name, templateFullName

    = 'template:components/' + name, templateRegistered = this.container && this.container.has(templateFullName); if (templateRegistered) container.injection(fullName, 'layout', templateFullName);
  47. Component Lookup Em.ComponentLookup.lookupFactory var Component = container.lookupFactory(fullName); if (templateRegistered ||

    Component) if (!Component) { container.register(fullName, Ember.Component); Component = container.lookupFactory(fullName); }
  48. Component Lookup app/components/x-foo.js app/templates/components/x-foo.hbs Files looked up:

  49. app/components/x-foo.js app/templates/components/x-foo.hbs Component Lookup Files looked up:

  50. Component Lookup app/components/x-foo.js // packages/ember-handlebars/lib/component_lookup.js#L16 // Ember.ComponentLookup#lookupFactory var Component =

    container.lookupFactory(fullName);
  51. Component Lookup app/components/x-foo.js app/templates/components/x-foo.hbs Files looked up:

  52. Component Lookup app/templates/components/x-foo.hbs // packages/ember-handlebars/lib/component_lookup.js#L13 // Ember.ComponentLookup#lookupFactory templateFullName = 'template:components/'

    + name; container.injection(fullName, 'layout', templateFullName);
  53. Magic?

  54. Nope, Just Javascript