angular.element vs document.getElementById或带有旋转(忙碌)控件的jQuery选择器


157

我使用的是Spin控件的“ Angularized”版本,如此处所述:http : //blog.xvitcoder.com/adding-a-weel-progress-indicator-to-your-angularjs-application/

我对所示解决方案不满意的一件事是在服务中使用jQuery,该服务有效地将旋转控件附加到DOM元素。我更喜欢使用角度构造来访问元素。我还想避免将微调器需要附加到服务内的元素的ID进行“硬编码”,而应使用在服务(单个)中设置ID的指令,以便该服务的其他用户或服务本身不需要知道这一点。

我在为angular.element给我们提供什么而在同一个元素id给我们提供了什么document.getElementById方面挣扎。例如。这有效:

  var target = document.getElementById('appBusyIndicator');

这些都不做:

  var target = angular.element('#appBusyIndicator');
  var target = angular.element('appBusyIndicator');

我显然正在做某事,应该是很明显的错误!有人可以帮忙吗?

假设我可以完成上述工作,那么尝试替换jQuery对元素的访问时也会遇到类似的问题:例如$(target).fadeIn('fast'); 有效 angular.element('#appBusyIndicator').fadeIn('fast')angular.element('appBusyIndicator').fadeIn('fast')无效

有人可以给我指出一个很好的文档示例,该文档阐明了Angular“元素”和DOM元素的使用吗?Angular显然以其自身的属性,方法等“包装”了元素,但通常很难获得原始值。例如,如果我有一个<input type='number'>字段,并且当用户键入“-”(不带引号)时,我想访问ui中可见的原始内容,我什么也没得到,大概是因为“ type = number”表示Angular正在拒绝输入,即使它在UI中是可见的,我也想看到它,以便我可以对其进行测试并清除。

任何指针/答案表示赞赏。

谢谢。


5
如果您正在加载jQuery,则angular.element是jQlite对象或jQuery对象。
2013年

Answers:


226

可以像这样工作:

var myElement = angular.element( document.querySelector( '#some-id' ) );

您将本Document.querySelector()机Javascript调用包装到该angular.element()调用中。因此,您总是在jqLit​​ejQuery对象中获取元素,具体取决于是否jQuery可用/加载。

官方文件angular.element

如果jQuery可用,angular.element则为该jQuery函数的别名。如果jQuery不可用,则angular.element委托Angular的内置子集jQuery,该子集称为“ jQuery lite”或jqLit​​e

中的所有元素引用Angular始终使用jQueryjqLite(例如,指令编译或链接函数中的element参数)包装。它们绝不是原始DOM参考。

如果您确实想知道为什么使用document.querySelector(),请阅读此答案


41
有什么理由会喜欢document.querySelector('#...')而不是简单地使用document.getElementById()?
加藤2014年

4
您也可以在角度元素上执行此操作:var elDivParent = angular.element(elem [0] .querySelector('#an-id'));, elem是角度元素。这样,您可以在元素内部进行搜索。对于单元测试很有用。
unludo 2014年

4
@Kato有关此答案的更多信息。希望能有所帮助。
kaiser 2015年

与谷歌地图API的工作,而这个工作:var autocomplete = new google.maps.places.Autocomplete( $document[0].querySelector('#address'), { types: ['geocode'], componentRestrictions: {country: 'us'} } );。感谢小费@kaiser。出于某种原因,maps api抱怨我在使用第一个参数时传递的不是输入angular.element(document.querySelector('#address')),而是一切顺利。
nymo '16

49

如果尚未阅读angular 元素文档,则应该阅读它,这样您就可以了解jqLit​​e支持的内容以及-jqlite是内置在angular中的jquery的子集。

这些选择器不能单独与jqLit​​e一起使用,因为不支持ID的选择器

  var target = angular.element('#appBusyIndicator');
  var target = angular.element('appBusyIndicator');

因此,要么:

  • 您单独使用jqLit​​e,比jquery限制更多,但在大多数情况下足够了。
  • 或者您将完整的jQuery库包含在您的应用程序中,并像普通的jquery一样在您真正需要jquery的地方使用它。

编辑:请注意,jQuery应该 angularJS 之前加载,以便优先于jqLit​​e:

真正的jQuery始终优先于jqLit​​e,前提是它是在DOMContentLoaded事件触发之前加载的。

Edit2:我之前错过了问题的第二部分:

的问题<input type="number">,我认为这不是一个有角度的问题,它是原生 html5数字元素的预期行为。

即使您尝试使用jquery .val()或raw .value属性检索它,它也不会返回非数字值。


2
我们有完整的jQuery库-否则我上面解释的$方案将不起作用。我的问题是为什么$可以工作,但是angular.element不能工作-即使可以使用完整的jQuery。
irascian

1
您是在angular.js之前还是之后包含jQuery?它应该包括角度之前。通过ID选择:用jQuery可用的工作jsbin.com/ohumiy/1/edit
加斯特

1
他们正在另一条指令中工作(例如,使用id访问angular.element)。问题似乎是该控件通过将自身附加到该元素而工作的方式,尽管我不明白为什么相同的jQuery对等物应该直接起作用。直接使用jQuery我的指令HAS具有关闭标签-自关闭标签不起作用(仅空白屏幕没有错误),这使我怀疑控件。
irascian

2
在第二点,还有一个类似于view $ value的东西可以用来检索元素的内容,但是在输入type = number的情况下,用户输入了“-”,则为空。我想要一个类似$ rawInputValue的属性来查看Angular介入之前的内容,因为即使我在指令中无法通过编程方式访问它,“-”仍位于UI中。
irascian 2013年

27
var target = document.getElementById('appBusyIndicator');

等于

var target = $document[0].getElementById('appBusyIndicator');

1
最好使用第二个示例来确保您的依赖项是显式的并且可以被模拟,对吧?
路加福音

应该,但是我想在angular 2+中,我们更多地依赖打字稿功能。不必再担心这些问题:)
Dasun

17

我认为这不是使用角度的正确方法。如果不存在框架方法,请不要创建它!这意味着框架(此处为角形)无法通过这种方式工作。

使用angular时,您不应像这样(jQuery方式)操作DOM,而应使用诸如

<div ng-show="isLoading" class="loader"></div>

或创建自己的指令(您自己的DOM组件)以对其进行完全控制。

顺便说一句,您可以在此处看到http://caniuse.com/#search=queryselector querySelector受到很好的支持,因此可以安全使用。


2
你是绝对正确的。在我认为需要手动操作DOM的90%以上的案例中,我最终重构了代码以消除需求,最终使代码更加简洁。
Stephen Chung

17

如果有人正在使用gulp,则如果我们使用它会显示一个错误document.getElementById(),建议使用,$document.getElementById()但它不起作用。

用 -

$document[0].getElementById('id')

为什么在这里角度注入数组?
彼得

16

您可以使用$ document访问元素(需要注入$ document)

var target = $document('#appBusyIndicator');
var target = $document('appBusyIndicator');

或使用角度元素,可以按以下方式访问指定的元素:

var targets = angular.element(document).find('div'); //array of all div
var targets = angular.element(document).find('p');
var target = angular.element(document).find('#appBusyIndicator');

1
find()-仅限按标签名称查找
RJV

angular.element(document).find('。someClass'); 工作完美。
Nishant Baranwal '17年

10

您应该在控制器中注入$ document,并使用它代替原始文档对象。

var myElement = angular.element($document[0].querySelector('#MyID'))

如果不需要jQuery样式元素换行,则$ document [0] .querySelector('#MyID')将为您提供DOM对象。


1
您也可以直接引用window.document而不是使用Angulars $ document服务开销。
MatBee 2015年

5
当然,如果您不担心在单元测试中嘲笑$ document,可以这样做
Adamy 2015年

我不清楚:我收到此警告:您应该使用$ document服务而不是默认的document对象,但这意味着什么?关于它的任何文档吗?谢谢!
realnot

@realnot,您可以从JavaScript的任何位置访问HTML DOM文档对象。w3schools.com/jsref/dom_obj_document.asp
Adamy

6

这对我很好。

angular.forEach(element.find('div'), function(node)
{
  if(node.id == 'someid'){
    //do something
  }
  if(node.className == 'someclass'){
    //do something
  }
});

3
元素未定义?angular.element.find不是我在没有JQuery的情况下尝试使用的功能。
降落

3
请不要这样做。使用其他示例之一。这根本不使用哈希表查找优化。
MatBee 2015年

4

改善kaiser的答案:

var myEl = $document.find('#some-id');

别忘了注入$document您的指令


21
element.find:的角度文档中所述find() - Limited to lookups by tag name,它不适用于id。另外,您还有一个额外的结帐时间)
paaat 2015年

3

也许我来不及在这里,但这可以工作:

var target = angular.element(appBusyIndicator);

注意,没有appBusyIndicator,它是纯ID值。

幕后发生的事情:(假设它应用在div上)(取自angular.js行号:2769起……)

/////////////////////////////////////////////
function JQLite(element) {     //element = div#appBusyIndicator
  if (element instanceof JQLite) {
    return element;
  }

  var argIsString;

  if (isString(element)) {
    element = trim(element);
    argIsString = true;
  }
  if (!(this instanceof JQLite)) {
    if (argIsString && element.charAt(0) != '<') {
      throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
    }
    return new JQLite(element);
  }

默认情况下,如果页面上没有jQuery,将使用jqLit​​e。该参数在内部被理解为id,并返回相应的jQuery对象。


我现在已经使用Angular 1.5.8进行了尝试。普通ID返回空结果。angular.element("#myId")效果很好。
Gosha U.18年

也许您的页面上有jQuery?
维沙尔·阿南德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.