【问题标题】:Angular's use of Inline JavaScript in HTML attributes is not "bad practice"? [closed]Angular 在 HTML 属性中使用内联 JavaScript 是不是“坏习惯”? [关闭]
【发布时间】:2013-01-25 11:10:37
【问题描述】:

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

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

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

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

【问题讨论】:

  • 我个人不喜欢内联的任何内容,并且会避免类似的事情,尽管这是一个意见问题。从理论上讲,如果有人使用内联,如果代码仍然有效,我猜有人可以使用它。如果是我,我会避免任何 HTML 定义的内联事件。
  • 我从未使用过 angularjs,但它看起来像一个模板框架,所以我必须多看一下才能确定。如果它在 HTML 上呈现,它可能有也可能没有“ng-click”属性,你确定它真的是内联的,还是在模板“生成”时创建一个绑定事件的 JS?虽然我对 Angularjs 不太熟悉,可能它只是内联事件,但据说它正在为你做模板,这可能是人们想要使用它的原因(尽管我个人认为我不喜欢那个库,再次,意见问题所以人们可能会否决这个问题)。
  • 它实际上不是内联的。将属性的内容设置为setImage(img) 实际上不会执行绑定。解析模板的脚本将。
  • AngularJS(和 ReactJS)是突兀的 javascript 框架,它将静态数据层 (HTML) 与处理该数据所需的逻辑 (Javascript) 耦合在一起。这是不好的做法。您实际上是在将您的开发人员锁定在 Google(或 Facebook)产品中。示例:您花了 2 年时间编写 AngularJS 应用程序,现在您想迁移到 ReactJS,因为它具有更快的性能。如果您已将逻辑与数据分离,则可以重用您的 HTML 模板。但是,现在你被困在继续使用 AngularJS 或用 ReactJS 重写你的前端。

标签: javascript angularjs


【解决方案1】:

真的,这一切都归结为您的视图代码必须以某种方式连接到您的应用程序逻辑中。 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 社区已经确定以这种方式编写大型应用程序并不真正站得住脚,部分原因是视图和模型对象之间的脱节(如代码 sn-p 中的 cmets 所示) ,这就是为什么我们首先拥有像 Angular 这样的框架。

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

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

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

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

My response 也适用于这里:

在像 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-clickng-submit 等时,您将在这些元素上设置事件处理程序,这些处理程序调用应该委托给模型对象的函数。使用 ng-showng-repeat 等时,您正在为更改视图的模型事件设置回调。

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

所以,最后,&lt;a ng-click="model.set({selected: true})"&gt; 添加的依赖项实际上并不比

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

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

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

(注意:实际上,Angular 版本应该是&lt;a ng-click="select()"&gt;,作用域上的select 方法就像Backbone 示例中视图中的select 方法。)

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

【讨论】:

  • 我觉得 Angular 的声明式事件定义更安全的另一个额外原因是,列出 ng-click 的方法通常位于该视图控制器的 $scope 上,而普通 HTML/JS 中的内联 onClick 是全局方法调用。
  • 范围是角度正常而内联 onclick 不好 IMO 的原因
  • 我可能会因为这样说而受到批评,但是当您有另一个想要重用代码的项目时会发生什么?您现在是否必须进入每个项目并将 ng-click="model.set({selected: true}) 添加到您想要使用它的所有内容中。如果您现在想更改内容会发生什么,您必须编辑 html对 javascript 进行更改,而不仅仅是将行为作为一个单独的问题进行编辑。我想全力以赴,但我仍然担心它对 HTML 的过度依赖程度。
  • 但是,如果您最终不得不将同一个事件绑定到页面上的多个元素,那么您需要将 ng-click 单独附加到所有元素,就在标记中。我觉得在过去的 5 年里我一直在学习像这样的内联 javascript(不要试图说服我它不是——你实际上是从 HTML 中的元素定义中调用方法 select())是不好的做法,只是被告知“只要它是一个鼓励它的javascript框架就可以了!”。只是……感觉不对。关注点分离发生了什么?
  • @nzifnab 使用 Backbone 示例,如果每个链接都不应该触发 select 事件怎么办?您可以向模板和选择器添加一个类,但是很容易意外地更改模板中的类而没有意识到您破坏了您的视图。您可以添加一些其他 data- 属性,但是当您想添加新链接时,必须在任何地方复制粘贴 ng-click 有什么不同? ng-click 等是对非全局对象上的方法的绑定 ($scope),以明显的声明方式编写。 (复制/粘贴问题也可以通过指令来解决。)
猜你喜欢
  • 1970-01-01
  • 2020-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-17
  • 1970-01-01
  • 2011-11-04
相关资源
最近更新 更多