50

当我阅读 Angular 教程时,我真的很喜欢它,但“ng-click”不等同于内联 onClick 吗?我的理解是 JavaScript 社区已经确定 HTML 中的内联 JavaScript 事件处理程序是“不好的做法”。

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

很高兴知道为什么在使用 Angular 时这不再被认为是“不正确的”。

来源:http ://docs.angularjs.org/tutorial/step_10

4

1 回答 1

59

实际上,这一切都归结为您的视图代码必须以某种方式连接到您的应用程序逻辑中。AngularJS 的最佳实践通常表明您应该编写自己的模型(代表您的业务领域的对象)并将它们附加到范围。想象一下这样的代码:

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

视图显示“单击此图像时,它将在 myProfile 上调用 setMainImage()。” 业务逻辑在里面myProfile,可以测试等等。视图只是一个钩子。

在更“传统”或“香草”的 jQuery 设置中,您必须编写如下内容:

$("#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?
});

当然,JavaScript 社区已经确定以这种方式编写大型应用程序并不真正站得住脚,部分原因是视图和模型对象之间的脱节(如代码片段中的注释所示),这就是为什么我们首先拥有像Angular这样的框架。

所以,我们知道这个原生 jQuery 代码并不理想,但我们仍然不确定整个ngClick事情。让我们将它与另一个非常流行的提供 MV* 架构的 JavaScript 框架 Backbone 进行比较。在最近关于 AngularJS 的 RailsCasts 节目中,有人问了一个非常相似的问题

只是我,还是 AngularJS 看起来很糟糕?Ryan,不要误会我的意思,这一集很棒,但我不相信这个框架。

所有这些ng-show,看起来ng-repeatng-class像旧的 Java 的 JSF 和类似的框架。它还使用ng-submit和强制执行突兀的 JS ng-click

所以我的观点是:你的观点很容易变得混乱并完全依赖它。其他框架(如 Backbone)的优点是在表示和行为(较少或没有依赖关系)和结构化客户端应用程序 (MVVM) 之间分离关注点。

我的回答也适用于这里:

在像 Backbone 这样的框架中,您将拥有类似以下代码(取自 Backbone 网站,减去几行代码):

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});
  },

});

在这个作为视图的对象中,您正在为各种元素设置事件处理程序。这些事件处理程序调用视图对象上的函数,这些函数委托给模型。您还可以在各种模型事件(例如change)上设置回调,然后调用视图对象上的函数来相应地更新视图。

在 Angular 中,DOM 是你的视图。使用ng-click,ng-submit等时,您将在这些元素上设置事件处理程序,这些处理程序调用应该委托给模型对象的函数。使用ng-show,ng-repeat等时,您正在为更改视图的模型事件设置回调。

AngularJS 在幕后为您设置这些 [钩子和] 回调的事实是无关紧要的;这与 Backbone 之类的唯一区别在于,Angular 允许您以声明方式编写视图——您描述视图什么——而不是命令式地描述视图的作用

所以,最后,<a ng-click="model.set({selected: true})">真正添加的依赖项不超过

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

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

...但它肯定是少了很多代码。;)

(注意:实际上,Angular 版本应该是<a ng-click="select()">,并且select作用域上的select方法类似于 Backbone 示例中视图中的方法。)

现在,也许一个合理的担忧是您不喜欢标记中的事件挂钩。就个人而言,我非常喜欢 Angular 视图的声明性特性,您的标记描述了视图是什么,并且您在事件(无论是用户生成的还是模型中的简单更改)和您的视图之间有两种方式绑定——我发现我写连接事件的样板代码要少得多(尤其是由模型更改驱动的视图更改),而且我认为总体上更容易推理视图。

于 2013-02-10T02:17:07.130 回答