【问题标题】:"disabling" ngAria using Angular Material使用 Angular 材质“禁用”ngAria
【发布时间】:2017-01-25 00:45:12
【问题描述】:

我正在开发一个托管在 SharePoint 2013 中的 Angular 应用程序,并且(我认为)遇到了 ngAria$ariaProvider 的问题。

问题是,当我单击链接以将<md-dialog> 元素作为模式打开时,UI 线程被锁定约 30-40 秒。通过调试,我能够将其追溯到一个方法,该方法包含在 Angular Material .js 中,名为 walkDOM(element)

应用程序在本地运行良好(没有 SharePoint),但在 SharePoint 环境中挂起。我认为这种方法是有问题的,因为它在 SharePoint 中遍历的 DOM 树比开发中的要大得多。在模态打开事件触发后,walkDOM() 方法被触发,并为大多数 DOM 元素添加一个aria-hidden="true" 值。由于 SharePoint 具有复杂的 DOM 结构,我认为这是导致挂断的原因。我能够调试并看到断点连续触发。我还可以看到属性是在挂断之后添加的,而不是事先存在的。

我想禁用此遍历,但到目前为止还没有找到可接受的方法来执行此操作。我已经关注了这个线程并意识到我可能无法访问我感兴趣的方法:https://github.com/angular/material/issues/600。我知道禁用 Aria 是不好的做法,但我只是试图阻止导致 UI 线程被锁定这么长时间的 DOM 遍历。我已尝试使用以下代码覆盖/配置 Angular 应用程序的 Aria 组件(此线程中建议使用后者 sn-p:How do I disable ngAria in ngMaterial?):

angular
.module('app', ['ui.router', 'ngMaterial', 'ngAria'])
...
.config(function ($ariaProvider) {
  $ariaProvider.config({
    ariaValue: true,
    ariaHidden: false,
    tabindex: false
  });
})
.decorator('$mdAria', function mdAriaDecorator($delegate) {
  $delegate.expect = angular.noop;
  $delegate.expectAsync = angular.noop;
  $delegate.expectWithText = angular.noop;
  return $delegate;
});

有什么方法可以做我想做的事吗?如果可能,我想避免重写应用程序以不使用模式。我想过写一个全局的walkDOM()方法,但收效甚微。

任何帮助将不胜感激。谢谢!

编辑:这是将aria 属性添加到DOM 结构的方式以及walkDOM() 方法的工作方式的问题。这与此问题中解决的路由/模型状态管理无关:How to prevent view redraw when changing route in AngularJS

【问题讨论】:

  • walkDom 是 Doug (AFAIK) 的一个 DOM 遍历函数。不要搞砸了,因为它也可能在其他地方使用。您是否参考了 ngMaterial 中实现 walkDOM 的任何代码?
  • @sabithpocker 我正在查看的方法看起来像是专门用于对话框:github.com/angular/material/blob/…
  • 感谢@PaulSweatte 的评论,但我认为您发布的链接与我遇到的问题不同。我在上面遇到的问题是 Angular Material 代码以及它如何遍历大型 DOM 结构的问题。

标签: javascript angularjs freeze wai-aria angularjs-material


【解决方案1】:

使用 getter 拦截 parentNode 内部的 walkDOM 属性检查。例如:

function getter() 
  {
  return document.documentElement; 
  }

 function isNodeOneOf(elem, nodeTypeArray) 
   {
   if (nodeTypeArray.indexOf(elem.nodeName) !== -1) 
     {
     return true;
     }
   }

 function walkDOM(element) 
  {
  var isHidden;
  var children = element.parentNode.children;

  console.log(Date() + element.innerText);
    
  while (element.parentNode) 
    {
    if (element === document.body) 
      {
      console.log(Date());
      return;
      }
  
  
    for (var i = 0; i < children.length; i++) 
      {
      console.log(Date());
    // skip over child if it is an ascendant of the dialog
    // or a script or style tag
      if (element !== children[i] && 
        !isNodeOneOf(children[i], ['SCRIPT', 'STYLE'])
       ) 
         {
         children[i].setAttribute('aria-hidden', isHidden);
         }
      }

    walkDOM(element = element.parentNode);
    }
  }

Object.defineProperty(HTMLElement.prototype, 'parentNode', 
                      { get: getter });

walkDOM(document.getElementById("foo") );
<section>
  <p>
    <span>
      <a>
        <strong>
          <span id="foo">Hi</span>
        </strong>
      </a>
    </span>
  </p>
</section>

在上述上下文中,getter 是:

用作属性的 getter 的函数,如果没有 getter,则为 undefined。函数返回将用作属性的值。

参考文献

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-09
    • 2020-01-05
    • 2018-02-16
    • 2016-11-10
    • 2018-06-17
    • 2019-06-29
    • 2016-09-08
    • 1970-01-01
    相关资源
    最近更新 更多