2013-02-10 5 views
49

Wie ich die Angular-Tutorials gelesen habe, mag ich wirklich eine Menge davon, aber ist nicht "ng-klick" das Äquivalent eines Inline-OnClick? Mein Verständnis war, dass die JavaScript-Community Inline-JavaScript-Event-Handler in Ihrem HTML festgestellt hatte, war "schlechte Praxis".Angulars Verwendung von Inline-JavaScript in HTML-Attributen ist nicht "schlechte Praxis"?

<img ng-src="{{img}}" ng-click="setImage(img)"> 

Es wäre schön zu wissen, warum dies bei Verwendung von Angular nicht mehr als "falsch" angesehen wird.

Quelle: http://docs.angularjs.org/tutorial/step_10

+0

Ich mag nichts inline persönlich und würde so etwas vermeiden, obwohl das eine Art Frage ist. Theoretisch, wenn jemand inline verwendet, wenn der Code noch funktioniert, denke ich, dass jemand ihn benutzen könnte. Wenn ich es wäre würde ich HTML-definierte Inline-Events vermeiden. – sajawikio

+0

Ich habe nie angularjs benutzt, aber es sieht wie ein Template-Framework aus, also müsste ich mehr nachsehen, um sicher zu gehen. Wenn es in HTML gerendert wird, hat es vielleicht ein "ng-click" -Attribut, ist es sicher, dass es wirklich inline ist, oder erzeugt es einen JS, der das Ereignis bindet, wenn die Vorlage "generiert" wird? Angularjs kenne ich zwar nicht so gut, wahrscheinlich macht es das Event nur inline, aber angeblich tut es für Sie Templating, was vielleicht der Grund sein könnte, warum man es benutzen möchte (obwohl ich persönlich diese Bibliothek nicht mag Frage so ppl kann diese Frage ablehnen). – sajawikio

+3

Es ist nicht wirklich inline. Wenn der Inhalt des Attributs auf '' setImage (img) '' gesetzt wird, wird die Bindung nicht ausgeführt.Ein Skript, das die Vorlage analysiert, wird dies tun. – nikola

Antwort

59

Wirklich, es kommt alles auf die Tatsache, dass Ihre Ansicht Code in Ihre Anwendungslogik irgendwie süchtig werden muss. Best Practices für AngularJS geben im Allgemeinen an, dass Sie Ihre eigenen Modelle - Objekte, die Ihre Geschäftsdomäne darstellen - schreiben und diese an den Bereich anhängen müssen. Stellen Sie sich vor, einige Code wie folgt aus:

<img ng-src="{{img}}" ng-click="myProfile.setMainImage(img)"> 
myApp.controller("ProfileController", function($scope, myProfile) { 
    $scope.myProfile = myProfile; 
}); 

Der Blick sagt "wenn dieses Bild geklickt wird, wird es setMainImage() auf MyProfile nennen." Die Geschäftslogik ist innerhalb myProfile, wo es getestet werden kann, usw. Die Ansicht ist nur ein Haken.

In einem „traditionellen“ oder „Vanille“ jQuery-Setup, dann würden Sie so etwas wie die folgenden schreiben müssen:

$("#someId img").on('click', function() { 
    var img = $(this).attr('src'); 
    myProfile.setMainImage(img); // where does myProfile come from here? 
           // how does it update the view? 
}); 

Natürlich hat sich die JavaScript-Gemeinschaft festgestellt, dass das Schreiben großer Anwendungen auf diese Weise ist nicht wirklich haltbar, teilweise aufgrund der Diskrepanz zwischen den Ansichten und den Modellobjekten (wie durch die Kommentare im Code-Snippet angedeutet), weshalb wir Frameworks wie Angular an erster Stelle haben.

Also, wir wissen, dass dieser native jQuery-Code nicht ideal ist, aber wir sind immer noch nicht sicher über die ganze ngClick Sache. Vergleichen wir es mit einem anderen sehr beliebten JavaScript-Framework, das eine MV * -Architektur, Backbone, bietet. In einer Episode letzten Railscasts auf AngularJS, someone asked a very similar question:

Ist es nur mich, oder AngularJS sieht so eine schlechte Idee? Ryan, versteh mich nicht falsch, die Episode war großartig, aber ich bin nicht von dem Framework überzeugt.

All das ng-show, ng-repeat, ng-class sind wie die alten Java-JSF und ähnliche Frameworks aussehen. Es erzwingt auch aufdringliche JS mit ng-submit und ng-click.

Also mein Punkt ist: Ihre Sicht wird leicht überladen und völlig davon abhängig. Der Vorteil anderer Frameworks wie Backbone besteht in einer Trennung der Belange zwischen der Darstellung und dem Verhalten (weniger oder keine Abhängigkeiten) und einer strukturierten Client-seitigen Anwendung (MVVM).

My response ist auch hier anwendbar:

In einem Framework wie Backbone, Sie so etwas wie den folgenden Code haben würde (von der Backbone-Website genommen, minus ein paar Zeilen):

var DocumentView = Backbone.View.extend({ 

    events: { 
    "dblclick"    : "open", 
    "click .icon.doc"   : "select", 
    "contextmenu .icon.doc" : "showMenu", 
    "click .show_notes"  : "toggleNotes", 
    "click .title .lock"  : "editAccessLevel", 
    "mouseover .title .date" : "showTooltip" 
    }, 

    open: function() { 
    window.open(this.model.get("viewer_url")); 
    }, 

    select: function() { 
    this.model.set({selected: true}); 
    }, 

}); 

In diesem Objekt , das eine Ansicht ist, richten Sie Ereignishandler auf verschiedenen Elementen ein. Diese Ereignishandler rufen Funktionen auf dem Ansichtsobjekt auf, die an Modelle delegieren. Sie richten auch Rückrufe für verschiedene Modellereignisse ein (z. B. change), die ihrerseits Funktionen auf dem Ansichtsobjekt aufrufen, um die Ansicht entsprechend zu aktualisieren.

In Angular ist das DOM Ihre Ansicht. Wenn Sie ng-click, ng-submit usw. verwenden, richten Sie Ereignishandler für diese Elemente ein, die Funktionen aufrufen, die an Modellobjekte delegieren sollen. Wenn Sie ng-show, ng-repeat usw. verwenden, richten Sie Callbacks für Modellereignisse ein, die die Ansicht ändern.

Die Tatsache, dass AngularJS diese [Hooks und] Callbacks hinter den Kulissen für Sie aufsetzt, ist irrelevant; der einzige Unterschied zwischen diesem und etwas wie Backbone ist, dass Angular können Sie Ihre Ansicht deklarativ schreiben - Sie beschreiben, was Ihre Sicht ist --aber als zwingend - beschreiben, was Ihre Sicht tut.

Also, am Ende, fügt <a ng-click="model.set({selected: true})"> wirklich nicht mehr Abhängigkeiten als

events: { 
    'click a': 'select' 
}, 

select: function() { 
    this.model.set({selected: true}); 
} 

... aber es ist sicher eine Hölle von viel weniger Code. .;)

(Anmerkung: wirklich, sollte die abgewinkelte Ausführung <a ng-click="select()"> und die select Methode auf dem Umfang wie die select Methode in der Ansicht im Backbone Beispiel wäre sein)

Nun, vielleicht ein legitime Bedenken ist, dass Sie die Ereignis-Hooks in Ihrem Markup nicht mögen. Persönlich bevorzuge ich die deklarative Natur von Angulars Ansichten, wobei Ihr Markup beschreibt, was die Ansicht ist, und Sie haben eine Zwei-Wege-Bindung zwischen Ereignissen (ob sie benutzergeneriert sind oder einfach Änderungen im Modell) und Ihre Ansichten - finde ich Ich schreibe viel weniger Code, um Ereignisse zu verknüpfen (insbesondere Änderungen in der Ansicht, die durch Änderungen in den Modellen ausgelöst werden), und ich denke, dass es einfacher ist, über die Ansicht im Allgemeinen nachzudenken.

+0

Danke für die gründliche Antwort. Das hilft definitiv, Dinge zu klären. Du hast auch viele der Grippes berührt, die ich mit Backbone habe. Ich schreibe eine Menge Code. – AndrewHenderson

+13

Ein weiterer zusätzlicher Grund, warum ich mich bei Angulars deklarativer Ereignisdefinition sicherer fühle, ist, dass eine Methode, die ng-click auflistet, typischerweise im $ Bereich des Controllers dieser Ansicht liegt, während ein inline onClick in Vanille HTML/JS ein globaler Methodenaufruf ist. – checketts

+0

Guter Punkt. Ich stimme zu. Das ist eine wichtige Unterscheidung. – AndrewHenderson

Verwandte Themen