отключение ngAria с помощью Angular Material

Я разрабатываю приложение Angular, размещенное в SharePoint 2013, и (я думаю) сталкиваюсь с проблемами с ngAria и $ariaProvider.

Проблема в том, что когда я щелкаю ссылку, чтобы открыть элемент <md-dialog> в качестве модального, поток пользовательского интерфейса блокируется примерно на 30-40 секунд. Благодаря отладке я могу отследить его до одного метода, включенного в Angular Material .js, с именем walkDOM(element).

Приложение отлично работает локально (без SharePoint), но зависает в среде SharePoint. Я думаю, что этот метод проблематичен, потому что дерево DOM, которое он проходит в SharePoint, значительно больше, чем в разработке. После запуска модального события открытия запускается метод walkDOM(), который добавляет значение aria-hidden="true" к большинству элементов DOM. Из-за сложной структуры DOM в SharePoint я думаю, что это вызывает зависание. Я могу отлаживать и видеть непрерывное срабатывание точек останова. Я также вижу, что атрибуты добавляются после зависания и не присутствуют заранее.

Я хотел бы отключить этот обход, но пока не нашел приемлемого способа сделать это. Я следил за этой веткой и пришел к выводу, что, возможно, я не смогу получить доступ к интересующим меня методам: https://github.com/angular/material/issues/600. Я понимаю, что отключение Aria — плохая практика, но я просто пытаюсь предотвратить обход DOM, из-за которого поток пользовательского интерфейса блокируется на такое долгое время. Я попробовал следующий код, чтобы перезаписать/настроить компоненты Aria для приложения Angular (последний фрагмент, предложенный в этой теме: Как отключить ngAria в 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(). Это не имеет ничего общего с управлением состоянием маршрутизации/модели, как указано в этом вопросе: Как предотвратить перерисовку представления при изменении маршрута в AngularJS.


person awh112    schedule 16.09.2016    source источник
comment
walkDom это функция обхода DOM от Дуга (AFAIK). Не перепутайте это, так как это может быть использовано и из других мест. У вас есть ссылка на какой-либо код в ngMaterial, который реализует walkDOM?   -  person sabithpocker    schedule 16.09.2016
comment
@sabithpocker метод, на который я смотрю, выглядит так, как будто он специально предназначен для диалогов: github.com/angular/material/blob/   -  person awh112    schedule 16.09.2016
comment
Спасибо за комментарий @PaulSweatte, но я думаю, что ссылка, которую вы разместили, отличается от той, с которой я сталкиваюсь. Проблема, с которой я столкнулся выше, связана с кодом Angular Material и тем, как он пересекает большие структуры DOM.   -  person awh112    schedule 14.10.2016


Ответы (1)


Используйте геттер для перехвата проверки атрибута 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 это:

Функция, которая служит геттером для свойства, или undefined, если геттера нет. Возврат функции будет использоваться как значение свойства.

Ссылки

person Paul Sweatte    schedule 14.10.2016