Element vs document.getElementById 或者 jQuery 选择器,带有 spin (busy)控制

我正在使用“ Angularized”版本的自旋控制,正如这里记录的: http://blog.xvitcoder.com/adding-a-weel-progress-indicator-to-your-angularjs-application/

我不喜欢显示的解决方案的一个地方是在服务中使用 jQuery,它有效地将自旋控制附加到 DOM 元素。我更倾向于使用角构造来访问元素。我还希望避免对 spinner 需要附加到服务中的元素的 id 进行“硬编码”,而是使用一个指令来设置服务中的 id (singleton) ,这样服务的其他用户或服务本身就不需要知道这一点。

我正在纠结 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')则不会

有人能给我举一个文档的好例子,说明如何使用角度“元素”而不是 DOM 元素吗?角度显然“包装”的元素与自己的属性,方法等,但它往往很难得到原始值。例如,如果我有一个 <input type='number'>字段,当用户输入“——”(没有引号)时,我想访问 UI 中可见的原始内容,我什么也得不到,可能是因为“ type = number”意味着 Angular 拒绝输入,即使它在 UI 中可见,我想看到它,这样我就可以测试它并清除它。

感谢你的指点。

谢谢。

600704 次浏览

如果您还没有阅读角度 元素文档,那么您应该能够理解 jqLite 支持哪些内容,而 not-jqLite 是内置在角度中的 jquery 的子集。

仅使用 jqLite 的那些选择器 没用的,因为不支持 选择器 by id。

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

所以,要么:

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

编辑: 注意,为了优先于 jqLite,jQuery 应该加载 之前 angularJS:

真正的 jQuery 总是优先于 jqLite,前提是 在触发事件之前加载。

编辑2: 我之前漏掉了问题的第二部分:

<input type="number">,I 好好想想的问题不是角度的问题,而是 本地人 html5数字元素的预期行为。

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

可以是这样工作的:

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

本地 Javascript调用封装到 angular.element()调用中。因此,您总是获取 JqLiteJQuery对象中的元素,这取决于 jQuery是否可用/加载。

angular.element的正式文件:

如果 JQuery可用,则 angular.elementjQuery函数的别名。如果 jQuery 不可用,angular.element将委托给 jQuery的内置子集 角度,称为“ jQuery lite”或 JqLite

Angular中的所有元素引用总是用 JQueryjqLite包装(例如指令编译或链接函数中的元素参数)。它们从来都不是原始的 DOM引用。

如果你想知道为什么要使用 document.querySelector(),请阅读 这个答案

我不认为这是使用棱角的正确方法。如果框架方法不存在,就不要创建它!这意味着框架(这里是角度)不是这样工作的。

使用 angle 时,您不应该像这样操作 DOM (jquery 方式) ,而应该使用

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

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

顺便说一下,您可以看到这里 http://caniuse.com/#search=queryselector querySelector 得到了很好的支持,因此可以安全地使用。

Kaiser 的回答有所改进:

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

不要忘记在指令中注入 $document

这招对我很管用。

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

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

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

如果不需要 jquery 样式元素包装,$document [0] . querySelector (’# MyID’)将提供 DOM 对象。

也许我来得太晚了,但这个会有用的:

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,将使用 jqLite。参数在内部被理解为一个 id,并返回相应的 jQuery 对象。

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

等于

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

可以使用 $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');

如果有人使用 Gulp,它显示一个错误,如果我们使用 document.getElementById(),它建议使用 $document.getElementById(),但它不工作。

使用-

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