Joc pe Backbone și Ember

Așa că ați acceptat provocarea de a deveni groasă pe partea clientului; foarte bine. V-ați gândit la toate cadrele existente și nu sunteți siguri pe cine să alegeți? Nu esti singur. Citește mai departe.

Experienta mea, atunci cand invatam modul de scriere a aplicatiilor pe partea clientului, se dovedeste a fi abrupta si grea. Nu este ușor să alegeți în mod deliberat să utilizați MV * pe client pentru cineva care a scris JavaScript, bazat exclusiv pe jQuery și plugin-urile sale. Aceasta este o paradigmă cu totul nouă; necesită abilități de programare de bază și o înțelegere considerabilă a designului JavaScript (limba). Dacă experiența dvs. se referă la a mea, citiți mai departe!

Voi explica principalele diferențe dintre două dintre cele mai populare cadre client JavaScript: Backbone.js și Ember.js. Fiecare dintre aceste instrumente are puncte forte, precum și puncte slabe care vă pot ajuta să alegeți mai atent.

Disclaimer: ca profesioniști în domeniul software-ului, trebuie să ne ocupăm de diversitatea opiniei. Backbone și Ember sunt rezultate ale unor profesioniști cu experiență și cu experiență, precum dumneavoastră și cu mine. Un instrument nu este mai bun decât celălalt; ele servesc doar mulțimi diferite și, ergo, rezolvă diferite probleme. Mulțumesc Trek pentru sfatul solid.


Filosofia

Spinele este mult mai ușor de învățat decât Ember.

În primul rând, trebuie să înțelegeți că Backbone și Ember servesc mai ales mulțimi puțin diferite. În ceea ce privește complexitatea, Backbone este mult mai ușor de învățat decât Ember. Cu toate acestea, se spune că, odată ce ați învățat Ember, cu greu nu mai devine mai complexă. Luați cuvântul lui Trek pe el. Dacă începeți doar cu un anumit JavaScript real, atunci poate Backbone este instrumentul dvs. Dacă, totuși, știți că veți avea de-a face cu mult mai mult decât un simplu caz de utilizare sau două, atunci ați putea prefera Ember.

șira spinării

Jeremy Ashkenas a construit Backbone astfel încât ar fi posibil să scoate adevărul din DOM. Ceea ce vrea sa spuna prin aceasta este: orice afacere pe care ai facut-o folosind doar jQuery / Mootools / Prototype ar putea si ar trebui sa fie mai bine extrasa in structuri JavaScript - obiecte, daca vrei. În loc de a folosi DOM elemente pentru a defini elementele de afaceri și comportamentul dvs., Backbone vă invită să o faceți invers. Obiectele JavaScript sunt nucleul și DOM este doar o reprezentare a acestor date.

Cu Backbone, aveți câteva afirmații:

  1. Datele se află în obiecte JavaScript, nu în DOM
  2. Manipularea evenimentului se găsește în obiecte JavaScript, nu în legături de evenimente jQuery
  3. Modul în care salvați datele într-un server de backend se realizează prin intermediul obiectelor care conțin datele

Vi se oferă control complet asupra modului în care construiți aplicația. Backbone a fost menit să vă ofere o modalitate de bază de proiectare a obiectelor dvs. de model și a modului în care acestea interacționează între ele prin legarea evenimentului.

Redare HTML la DOM este de responsabilitatea dvs. Aveți libertatea de a alege orice motor de șablon: Mustache, DoT, Handlebars, Underscore etc. Backbone conține o Vedere prototip care are responsabilitatea de a articula DOM și nucleul dvs. JavaScript.

tăciuni aprinși

Când Tilde a început să construiască Ember, a făcut acest lucru cu un scop mult mai provocator: să să ofere convenții standard în dezvoltarea clientului, eliminând cât mai mult posibil. Rezultatul este un cadru mult mai ambițios care vizează o arhitectură previzibilă și o dezvoltare constantă.

Ember împărtășește câteva puncte comune cu Backbone în modul în care încearcă să tragă date și comportament din DOM prin furnizarea de prototipuri JavaScript extensibile, dar face acest lucru într-o manieră foarte diferită de cea a Backbone-ului.

Ember se află pe:

  1. Legarea datelor în două direcții: obiectele din Ember pot înregistra legături între ele. În acest fel, ori de câte ori o proprietate legată se schimbă, cealaltă este actualizată automat.
  2. Proprietăți calculate: dacă doriți să aveți o proprietate care este rezultatul unei funcții, puteți să o creați și să atribuiți o proprietate calculată de acea funcție.
  3. Șabloane actualizări automate: când un obiect este actualizat în aplicația dvs., toate afișările afișate în prezent pe ecran care sunt legate de obiectul respectiv reflectă automat modificarea, fără nici o placă de boiler.

Vizualizările DOM

Atât Backbone cât și Ember au concepte cheie comune, cum ar fi vizualizari. Ambele reprezintă DOM comunicare, respectiv. Modul în care realizează acest concept sunt oarecum diferite.

Voi folosi cazul de utilizare Todo pentru exemplele de mai jos, inspirat de prezentarea TodoMVC.

șira spinării

O vizualizare backbone ar putea fi ceva de genul:

var TaskView = Backbone.View.extend (tagName: "li", șablon: "task-template", render: function () : "mark_as_done", "change .body": "update_body", mark_as_done: function () / * cod aici * /, update_body: function () / * cod aici * /);

Aceasta este pur și simplu definiția părerii tale. Va trebui să instanțiați unul dacă doriți să fie în pagină. Ceva de genul asta va face truc:

var task_view = task nou (model: task_model); . $ ( "Corp") append (task_view.el);

Observați că trecem un model în așa fel încât să puteți păstra o referință la obiectul de date care alimentează șablonul. șablon proprietatea din interiorul vizualizării poate fi utilizată pentru a apela un șablon exterior, printr-un identificator. Am folosit ceva de genul asta în trecut:

var TaskView = Backbone.View.extend (template: "# task-template", render: function () this. $ el.html (Mustache.render ($ (this.template) model); // snip);

tăciuni aprinși

Ember are o abordare diferită a vederilor. De fapt, convenția afirmă că opiniile ar trebui să vorbească direct cu controlorii și nu cu modelele. Aceasta este o bună practică, dacă intenționați să urmați o arhitectură stabilă. Voi explica eșantionul pentru aceeași vizualizare:

var TaskView = Ember.View.extend (templateName: "task-template", mark_as_done: function () / * cod aici * /, update_body: function () / * cod aici * /);

Asta e. Dar unde sunt toate lucrurile de randare? Ei bine, Ember ridică acea boilerplate pentru tine. Pur și simplu spuneți ce este șablonul, controlerul care deține obiectul de date și apoi trebuie doar să îl adăugați la DOM.

var task_view = TaskView.create (controler: task_controller // Ember.ObjectController); task_view.append ();

Atunci când creați o instanță nouă de vizualizare, aceasta va lega conținutul controlerului (care poate fi un Ember.Object sau o listă a acestora) la vedere. Când decideți să adăugați vizualizarea la DOM, acesta va căuta șablonul și va plasa marcajul generat pentru dvs..

Gânduri

Spinele este mai explicit și mai puțin magic.

Spinele este mai explicit și mai puțin magic. Creați a Vedere, spune-i ce șablon să folosești și cum, să înregistrezi evenimentele și să faci ce trebuie să faci. Ei dețin pagina. Acesta este un început excelent pentru cei care provin dintr-un mediu jQuery. Cu toate acestea, atunci când ceva trebuie actualizat în DOM, vă veți confrunta cu unele boilerplate.

Cu Ember, actualizările sunt automate. Voi spuneți ce șablon este și că callback-urile sunt funcții în interiorul obiectului de vizualizare. Ori de câte ori un obiect este actualizat, vizualizarea actualizează automat pagina.

Unele legături comune de eveniment sunt construite în Ember, iar altele trebuie introduse în șablon. Este bine pentru cei care vin dintr-o perspectivă de backend, deoarece reduce boilerplate într-un mod considerabil.


Modelele de date

Modelele din Backbone și Ember sunt destul de asemănătoare. Ele dețin informații pentru o entitate comercială.

șira spinării

Un exemplu de model Backbone arată astfel:

var TaskModel = Backbone.Model.extend ();

Cu această linie simplă de cod, aveți un model de lucru cu ODIHNĂcomunicare completă încorporată. Ai metode cum ar fi Salvați să persiste datele și aduce să o încărcați gratuit; nu este necesar niciun plugin. Validarea este, de asemenea, construită în modul în care datele sunt salvate prin furnizarea unei valida callback, care returnează un boolean care spune că înregistrarea trebuie salvată sau nu. Punerea în aplicare a validării este încă pentru dezvoltator de a face.

Pentru a crea o nouă sarcină, instanțiați un nou TaskModel.

var task = TaskModel nou (body: "Făcând gazonul", done: false);

Puteți injecta atâtea atribute pe care le doriți, deoarece lista de atribute a sarcinii nu este strictă (gândiți-vă la ea ca la scheme,). Încă puteți seta o implicite proprietate atunci când se extinde Backbone.Model.

tăciuni aprinși

Cu Ember, nu există modele, doar obiecte. Poate arata cam asa:

Var TaskObject = Ember.Object.extend ();

Similar cu versiunea din spate, trebuie să vă extindeți Ember.Object pentru a crea o clasă de obiecte. Acesta moștenește toate funcționalitățile de bază pentru o clasă cu apeluri de apel atunci când devine schimbat, creat și distrus, printre alte caracteristici. Cu toate acestea, nu are comunicare de backend din cutie. Ember.Data este în curs de dezvoltare ca o extensie a Ember.Object de către echipa de bază Ember pentru a îndeplini această nevoie. Este deja utilizabil, dar nu este stabil în măsura în care documentația spune.

Obiectele ember sunt, de asemenea, considerate a fi scheme,. Pentru a injecta valorile implicite în obiecte ember, extindeți Ember.Object trecând un obiect cu atribute cât mai multe de care aveți nevoie.

var TaskObject = Ember.Object.extend (body: "Mow the grass", terminat: false);

Gânduri

Backbone-ul are o modalitate consolidată de sincronizare cu un strat de persistență ODIHNĂ și asta este o convenție bună acolo. Este un lucru mai puțin pe care trebuie să-l configurați pentru a lucra cu un server de backend.

Ember se străduiește să facă Ember.Data gata pentru utilizarea în producție și pare promițătoare. Chiar și așa, particularitatea obiectelor Ember având legături în două direcții face ca moartea să devină ușor de realizat conexiuni între obiecte.

În acest moment în citirea dvs., aveți un punct de inflexiune între stabilitatea Backbone în comunicarea cu serverul backend și legăturile lui Ember. Orice ar fi cel mai important pentru tine ar trebui să determine decizia ta.


Controlerele pentru lipici

Acesta este locul în care cadrele partajează. Ei au un decalaj conceptual enorm cu privire la modul în care să lipiți lucrurile împreună în aplicația dvs. În timp ce Backbone se străduiește să rămână cât mai simplu și mai flexibil posibil, Ember sacrifică mărimea codului pentru o arhitectură mai bună. Este un compromis, într-adevăr.

Avertisment: următoarele exemple nu conțin eșantioane de șabloane HTML.

șira spinării

După cum am remarcat, Backbone își propune simplitatea care se transformă în flexibilitate și atinge astfel de atribute prin intermediul lipsa unei clase de controler. Cea mai mare parte a workhorse este distribuită în jurul vizualizărilor, colecțiilor, modelelor și routerului (dacă alegeți să utilizați Backbone's Router).

Având în vedere o listă de sarcini care trebuie gestionate, ar fi necesar:

  • A Colectie pentru a stoca sarcinile.
  • A Model pentru a stoca informația unei sarcini.
  • A Vedere pentru a reprezenta colecția.
  • O alta Vedere pentru a reprezenta fiecare sarcină.
  • A Router pentru a gestiona adresele URL.

Cea mai mare parte a logicii aplicației va trăi în vizualizări, deoarece acestea leagă modele de DOM. Nu există o distincție clară a responsabilităților, deoarece viziunea face totul. Acesta poate fi bun pentru aplicații mici, care nu necesită o arhitectură solidă.

Pentru a afișa o listă de sarcini, ați ajunge la ceva de genul:

Colectie

var TaskList = Backbone.Collection.extend (model: Task);

Model

var TaskModel = Backbone.Model.extend ();

Vizualizări

var TaskListView = Backbone.View.extend (render: function () this. $ el.empty (); pentru (_i = 0, _i < this.collection.length; _i++)  var task = this.collection.models[_i]; this.$el.append(this.renderItem(task));  var tasks = this.$el.html(); this.$el.html(Mustache.to_html(template,  tasks: tasks, no_tasks: !this.collection.length )); , renderItem: function(task)  var view = new Row( model: task ); var el = view.render(); return el.el; , );
var TaskView = Backbone.View.extend (tagName: "tr", render: function () this. $ el.html (M.to_html (template, thismodel.attributes));

Router

var Router = Backbone.Router.extend (initialize: function () this.tasks = noua TaskList; this.view = noua TaskListView (colectia: this.tasks ,, tasks_list: function () this.view.render (); $ (".cache: prima"). html (this.view.el); start: function () Backbone.history.start pushState: true, root: "/ bilete /"););

Observați că colecția nu are un model propriu; mai degrabă, el delegă la o singură vedere de sarcină fiind redat și adăugat la rezultatul final pus pe pagină.

tăciuni aprinși

Numărul de clase necesare pentru a avea aceeași setare este puțin mai mare.

  • În loc de a Colectie, ai avea un ArrayController, care funcționează foarte mult.
  • Ai mai mult ObjectController pentru gestionarea unei singure sarcini.
  • În loc de a Model, ai avea un Obiect / DS.Model, care funcționează la fel.
  • Ați avea același tip Vederes.
  • A Router este de asemenea responsabil pentru gestionarea adreselor URL.

S-ar putea să vă gândiți că cele două cadre nu sunt prea diferite una de cealaltă. Este destul de tentant, dar nu este chiar adevărat. Unele diferențe deosebite sunt:

  1. Controlorul este responsabil pentru interacțiunea cu obiectele de date, nu cu vizualizarea.
  2. Opiniile sunt responsabile pentru manipularea DOM, nu controlerul.
  3. Punctele de vedere comunică cu controlorul, nu direct către obiectele de date.
  4. Datele care alimentează șablonul de vizualizare sunt de fapt obligatorii pentru datele controlerului.
  5. Router-ul este mai mult de a director de stat, care include mult mai mult decât manipularea adreselor URL.

Separarea preocupărilor este bună pe termen lung. Controlerul manipulează datele, vizualizările se ocupe de DOM, perioadă. Acest tip de decuplată și coezivă, fără boilerplateless design permite testare mai concentrată.

Implementarea pentru a afișa aceeași listă de sarcini ar fi ceva asemănător cu cele de mai jos, având în vedere o aplicație completă Ember:

Arhitectura rădăcină a aplicației

window.App = Ember.Application.create (); App.ApplicationController = Ember.ObjectController.extend (); App.ApplicationView = Ember.View.extend (templateName: "cerere");

Obiect

App.Task = Ember.Object.extend ();

controlerele

App.TasksController = Ember.ArrayController.extend (conținut: []);

Vedere

App.TasksView = Ember.View.extend (templateName: "my-list");

Router

App.Router = Ember.Router.extend (rădăcină: Ember.Route.extend (index: Em.Route.extend (route: '/', connectOutlets: funcția (router) router.get ('applicationController') .connectOutlet ("sarcini");));

În cazul lui Ember, nu se spune prea multe despre cum se fac lucrurile înăuntru. Toate boilerplate-ul este luat, astfel încât să vă puteți concentra asupra a ceea ce contează cu adevărat în aplicația dvs.: definiți un obiect de activitate, un controler al listei de sarcini cu un matrice numit conţinut, vizualizarea dvs. și ruterul le combină pur și simplu și le pune în pagină.

Gânduri

După ce a realizat cum funcționează Ember, începe să devină eliberator.

În mod previzibil, acest segment a fost cel mai greu de înțeles pentru ambele cadre. Rostul a fost cu siguranță mai ușor de învățat, iar natura sa flexibilă dă controlul asupra modului în care obiectele și obiectele se află DOM interacționa. Acest lucru ar putea fi bun pentru dvs., dacă într-adevăr aveți nevoie de acest tip de flexibilitate, dar totuși doriți să mențineți o structură pentru logica aplicației dvs. în partea JavaScript.

În ceea ce-l privește pe Ember, implementarea ei uluitoare poate fi înfricoșătoare la început. Cu toate acestea, după ce a realizat cum funcționează Ember, începe să devină eliberator. Toate convențiile setate pentru tine vă eliberează de pe platforma de boot și de configurație, permițându-vă să vă concentrați asupra aplicației. Acest lucru este similar cu ceea ce a făcut Rails pentru dezvoltarea de servere care a atras atenția atât de mult.


Ce le-a stabilit în afară?

Ember a fost menit să ridice povara obișnuită a dezvoltării JavaScript în browser.

Până în prezent, scopul de a arăta cele două instrumente a fost acela de a recunoaște scopul lor unic și nobil: de a delega putere la partea clientului, prin structura și metodă.

Rata de bază a spatelui este cu siguranță abordarea KISS. Acesta vă oferă minimul de a renunța la DOM ca susținător principal al aplicației dvs. și începeți să utilizați obiecte JavaScript real care pot fi testate și proiectate corespunzător.

Backbone vine cu colecții, modele, vederi și router, printre alte utilități mici. Sunteți liber să faceți ceea ce vă rog cu ei.

Ember, pe de altă parte, a fost construit cu o mentalitate diferită, deoarece vizează o modalitate mult mai convențională și mai avizată de a construi aplicații web. Ea abordează un set de probleme comune, cum ar fi boilerplate, legarea datelor și DOM templând astfel încât să nu trebuie să vă faceți griji de la început. Ember a fost menit să ridice povara obișnuită a dezvoltării JavaScript în browser.

Ember vine echipat cu obiecte, controlori, vizualizări cu auto-actualizare, mașini de stat, legături, observatori și un router (care este de asemenea o mașină de stat), toate acestea provocând o bună doză de convenții. Aveți o arhitectură deja proiectată și pregătită să începeți să lucrați fără a pierde concentrarea.


Concluzie

Gândiți-vă la diferența de învățare. Experiența și moștenirea dvs. culturală vor dicta cu fermitate cât de repede se alătură clientului. Dacă vă este frică de ce să faceți sau de cine să alegeți, atunci am lovit un nerv de-al tău și asta e bine! Vrei un răspuns bun pe care să alegeți? Ambii.

Este vorba despre JavaScript

Dacă nu sunteți sigur că chiar și jQuery face toată magia, începeți să învățați Backbone. Este mai ușor să începeți, iar documentația este ușor de citit și de înțeles. După ce ați terminat, începeți să construiți ceva. Du-te murdar. Verificați aceste tutoriale dacă aveți nevoie de ajutor.

Dacă sunteți încă în întuneric, citiți articolele lui Yehuda Katz despre cum funcționează JavaScript.

Odată ce veți obține o viziune mai bună asupra modului în care JavaScript funcționează ca o limbă, veți începe să înțelegeți mai bine modul în care obiectele interacționează unul cu celălalt. Când o faci, du-te la Ember. Este mai complicat la început, dar nu renunță. Începeți să citiți documentele și ghidurile. S-ar putea să doriți să verificați intrarea în blog a lui Trek Glowacki chiar înainte de a vă pune mâinile murdare.

Linia mea de fund

Personal, mă înclin spre Ember; Îmi place robustețea la o scară macro, și prefer, de asemenea, convențiile sale. Backbone este un instrument mai ușor de utilizat și mai ușor pentru aplicații mai mici sau caracteristici mici în interiorul unei aplicații existente.

Învăț în continuare atât, cât și câteva provocări:

  • Teste automate: cum să le faceți și ce suite de testare este mai bună. Qunit sau Jasmine? Headless (gândire PhantomJS), nod sau alergator de test de browser? Nu sunt sigur inca.
  • Încărcări de fișiere
  • Internaționalizarea

Care sunt gândurile tale în acest dezastru întreg? Aveți vreo provocare în minte? Orice dificultăți sau obstacole? Să-mi dai de veste!

Cod