Angular在HTML属性中使用内联JavaScript不是"不好的做法"吗?

And*_*son 50 javascript angularjs

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

<img ng-src="{{img}}" ng-click="setImage(img)">
Run Code Online (Sandbox Code Playgroud)

很高兴知道为什么在使用Angular时不再将其视为"不正确".

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

Mic*_*ley 59

实际上,这完全取决于您的视图代码必须以某种方式挂钩到您的应用程序逻辑中.AngularJS的最佳实践通常声明您应该编写自己的模型 - 代表您的业务域的对象 - 并将它们附加到范围.想象一下这样的代码:

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

该视图显示"单击此图像时,它将在myProfile上调用setMainImage()." 业务逻辑在内部myProfile,可以在其中进行测试等.视图只是一个钩子.

在更"传统"或"vanilla"的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?
});
Run Code Online (Sandbox Code Playgroud)

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

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

它只是我,还是AngularJS看起来如此糟糕?瑞恩,不要误会我的意思,这一集很棒,但我不相信这个框架.

所有这一切ng-show,ng-repeat,ng-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});
  },

});
Run Code Online (Sandbox Code Playgroud)

在此对象,您将在各种元素上设置事件处理程序.这些事件处理程序调用视图对象上的函数,该函数委托给模型.您还可以在各种模型事件(例如change)上设置回调,这些事件又调用视图对象上的函数来相应地更新视图.

在Angular中,DOM是您的视图.当使用ng-click,ng-submit等等,要设置这些元素,它调用应该委托给模型对象功能的事件处理程序.当使用ng-show,ng-repeat等你正在设置在不改变视图模型事件回调.

AngularJS为你设置这些[钩子和]回调的事实是无关紧要的; 这一点,像骨干之间的唯一区别是,角让你写你的看法声明-你的描述你的看法不是势在必行--rather -说明你的观点是什么.

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

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

select: function() {
  this.model.set({selected: true});
}
Run Code Online (Sandbox Code Playgroud)

...但它确实是一个很少代码的地狱.;)

(注意:实际上,Angular版本应该是<a ng-click="select()">,并且select范围上的方法将类似于selectBackbone示例中的视图中的方法.)

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

  • 使用Angular的声明性事件定义我觉得更安全的另一个原因是列出ng-click的方法通常位于该视图控制器的$ scope上,而vanilla HTML/JS中的内联onClick是一个全局方法调用. (13认同)
  • 但是如果您最终必须将同一事件绑定到页面上的多个元素,那么您需要在标记中单独将"ng-click"附加到所有这些元素.我觉得我在过去的5年里一直在学习像这样的内联javascript(并且不要试图说服我不是 - 你实际上是从HTML中的元素定义中调用方法`select()`)糟糕的做法,只是被告知"只要它是一个鼓励它的javascript框架就可以了!".它只是......感觉*错误*.关注点分离发生了什么? (5认同)
  • 范围是角度正常并且内联onclick是错误的IMO的原因 (4认同)
  • 我可能会说到这一点,但是当你想要重用代码的另一个项目时会发生什么?你现在必须进入每个项目并将ng-click ="model.set({selected:true})添加到你想要使用它的每件事物中.如果你想要改变东西,现在你必须编辑html会发生什么更改javascript而不是仅仅将行为编辑为一个单独的问题.我想全神贯注于角度,但我仍然担心它是如何过度依赖HTML. (2认同)
  • @nzifnab要使用Backbone示例,如果每个链接都不应该触发`select`事件怎么办?您可以向模板和选择器添加一个类,但是很容易意外地更改模板中的类而不会意识到您打破了视图.你可以添加一些其他的`data -`属性,但是当你想要添加一个新的链接时,不得不在任何地方复制粘贴`ng-click`这有什么不同呢?`ng-click`等是*绑定到非全局对象*(`$ scope`)上的方法,以明显和声明的方式编写.(通过指令也可以帮助复制/粘贴问题.) (2认同)