Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Legend of Zelda: A {{link-to}} the past

The Legend of Zelda: A {{link-to}} the past

This talk tries to demystify what happens under the covers when you click on a {{link-to}} helper in Ember. It attempts to dive a layer or two down in to what happens in the router when transitioning from one route to another.

The presentation has absolutely nothing to do with Zelda other than the title slide. I just got a chuckle every time I thought of the title. So I couldn't help myself.

For the best experience, start at slide #178. Once you reach the final slide, hold the left arrow key and flip back through every slide as fast as possible. I left a little surprise for those that came just for the Zelda reference.

Avatar for Aaron Chambers

Aaron Chambers

March 12, 2015
Tweet

More Decks by Aaron Chambers

Other Decks in Programming

Transcript

  1. WOW

  2. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile
  3. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile
  4. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile
  5. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile
  6. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile
  7. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile
  8. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile
  9. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile willTransition phase model resolution / validation phase sync exit / enter / setup phase
  10. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile willTransition phase model resolution / validation phase sync exit / enter / setup phase willTransition: function(transition) { }
  11. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile willTransition phase model resolution / validation phase sync exit / enter / setup phase willTransition: function(transition) { }
  12. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile willTransition phase model resolution / validation phase sync exit / enter / setup phase willTransition: function(transition) { }
  13. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile willTransition phase model resolution / validation phase sync exit / enter / setup phase
  14. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile willTransition phase model resolution / validation phase sync exit / enter / setup phase beforeModel: function() { },
  15. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile willTransition phase model resolution / validation phase sync exit / enter / setup phase afterModel: function() { },
  16. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile willTransition phase model resolution / validation phase sync exit / enter / setup phase beforeModel: function() { },
  17. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile willTransition phase model resolution / validation phase sync exit / enter / setup phase model: function() { },
  18. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile willTransition phase model resolution / validation phase afterModel: function() { }, sync exit / enter / setup phase
  19. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile willTransition phase model resolution / validation phase sync exit / enter / setup phase
  20. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile willTransition phase model resolution / validation phase sync exit / enter / setup phase deactivate: function(transition) { },
  21. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile willTransition phase model resolution / validation phase sync exit / enter / setup phase deactivate: function(transition) { },
  22. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile willTransition phase model resolution / validation phase sync exit / enter / setup phase activate: function() { },
  23. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile willTransition phase model resolution / validation phase sync exit / enter / setup phase setupController: function() { }
  24. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile willTransition phase model resolution / validation phase sync exit / enter / setup phase activate: function() { },
  25. // app/routes/user/profile.js export default Em.Route.extend({ beforeModel: function() { }, model:

    function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); // app/routes/application.js export default Em.Route.extend({ actions: { willTransition: function(transition) { } } }); // app/routes/about.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/about/faq.js export default Em.Route.extend({ deactivate: function() { }, actions: { willTransition: function(transition) { } } }); // app/routes/user.js export default Em.Route.extend({ beforeModel: function() { }, model: function() { }, afterModel: function() { }, activate: function() { }, setupController: function() { } }); /about/faq /users/1/profile willTransition phase model resolution / validation phase sync exit / enter / setup phase setupController: function() { }
  26. willTransition Hooks Resolved Models Deactivated Old Routes Activated New Routes

    /about/faq /users/1/profile /about/faq /users/1/profile willTransition beforeModel model afterModel deactivate activate setupController
  27. willTransition Hooks Resolved Models Deactivated Old Routes Activated New Routes

    /about/faq /users/1/profile /about/faq /users/1/profile willTransition beforeModel model afterModel deactivate activate setupController
  28. willTransition Hooks Resolved Models Deactivated Old Routes Activated New Routes

    /about/faq /users/1/profile /about/faq /users/1/profile willTransition beforeModel model afterModel deactivate activate setupController
  29. willTransition Hooks Resolved Models Deactivated Old Routes Activated New Routes

    /about/faq /users/1/profile /about/faq /users/1/profile willTransition beforeModel model afterModel deactivate activate setupController
  30. willTransition Hooks Resolved Models Deactivated Old Routes Activated New Routes

    /about/faq /users/1/profile /about/faq /users/1/profile willTransition beforeModel model afterModel deactivate activate setupController