Доступ к составленному DOM для полимерного элемента

Я пытаюсь получить доступ к отображаемому браузером DOM для полимерного элемента, совершенно не заботясь о том, какие биты из «светлого» или «теневого» DOM, как описано в http://www.polymer-project.org/platform/shadow-dom.html, но я не могу найти документацию по API на функции доступа, которые позволили бы мне сделать это.

Я вижу список .shadowRoots, который находится на полимерных элементах, и я вижу обычное свойство .children, но ни один из них не особенно полезен для получения содержимого, которое фактически отображается на странице.

Как правильно получить фрагмент DOM, который в данный момент виден в браузере? (или если кто-то знает, где это задокументировано на сайте полимеров, я бы тоже хотел это знать. Google не смог найти это для меня)


person Mike 'Pomax' Kamermans    schedule 01.05.2014    source источник


Ответы (2)


Общая идея состоит в том, чтобы рассматривать только ваш виртуальный DOM (и, что еще лучше, рассматривать только локальный DOM [разделяй и властвуй ftw]).

Поэтому сегодня нет (простого) способа изучить составленный DOM.

Со временем такой способ появится и для определенных специализированных целей, но я призываю вас попытаться принять ментальную модель, которая позволит вам не задавать этот вопрос.

person Scott Miles    schedule 01.05.2014
comment
это не ментальная модель: мне нужно знать, что браузер показывает пользователям, а не только какие потенциальные данные существуют =) - person Mike 'Pomax' Kamermans; 02.05.2014
comment
проблема, с которой я сталкиваюсь, заключается в том, что у меня есть пользовательский элемент, который содержит другие пользовательские элементы - полимер проходит через них и запускает события вставки dom, когда элементы фактически добавляются не в DOM, а в фрагмент dom : <a><b></b></a> сначала запускает вставку для b в безголовый domfragment, но затем никогда не запускает событие, когда этот фрагмент связан с a: как я узнаю, когда b действительно используется на странице, т.е. мой пользователь просматривает его, интерактивный с ним, и он находится внутри элемента a, поэтому я могу заставить b вести себя правильно - person Mike 'Pomax' Kamermans; 05.05.2014
comment
Я не уверен, к чему относятся события вставки dom. Если вы имеете в виду вызовы attachedCallback или attached, они запускаются только тогда, когда элемент становится частью основного документа. Если у вас есть встречный пример, вы должны опубликовать отчет об ошибке. - person Scott Miles; 05.05.2014
comment
Я попробовал attachedCallback, который сработал для b, когда он был прочитан Polymer, но до того, как его цепочка-предок включала a. - person Mike 'Pomax' Kamermans; 05.05.2014
comment
Я немного нервничаю из-за того, что мы ведем эту дискуссию под заголовком «сочиненный дом», поскольку это совсем не один и тот же вопрос. Fwiw, до сих пор вы не описали ни одной проблемы, которая на самом деле зависит от опроса составленного дерева. - person Scott Miles; 06.05.2014
comment
В любом случае attachedCallback запускается, когда узел считается прикрепленным к основному документу (а не когда он читается Polymer). К сожалению, характер окружающего дома и различные ссылки в этот момент могут зависеть от нескольких факторов. Если вы используете собственно Polymer, вы можете попробовать domReady вместо attached. Если вы используете какой-то другой вариант пользовательских элементов, попробуйте перейти на асинхронный режим из attachedCallback (например, используйте setTimeout или друзья ждут одну «задачу», прежде чем пытаться получить доступ к окружающему DOM). - person Scott Miles; 06.05.2014

Вот что я написал с той же целью:

  function getComposedDOMChildren (root) {
    if (root.shadowRoot) {
      root = root.shadowRoot;
    }
    var children = [];
    for (var i = 0; i < root.children.length; i++) {
      if (root.children[i].tagName === 'CONTENT') {
        children.push.apply(children, root.children[i].getDistributedNodes());
      } else if (root.children[i].tagName === 'SHADOW') {
        var shadowRoot = root;
        while (!shadowRoot.host) {
          shadowRoot = shadowRoot.parentNode;
        }
        children.push.apply(children, getComposedDOMChildren(shadowRoot.olderShadowRoot));
      } else {
        children.push(root.children[i]);
      }
    }
    return children;
  }

Он возвращает массив с дочерними элементами root в соответствии с составленным DOM. Он работает, заходя в теневой корень и заменяя все <content> элементы тем, что в них фактически отображается, и рекурсивно используя более ранний теневой корень, когда найдены <shadow> элементы.

Конечно, чтобы получить все дерево DOM, нужно выполнить итерацию по возвращаемому массиву и вызвать getComposedDOMChildren для каждого элемента.

Что-то типа:

function traverse (root) {
  var children = getComposedDOMChildren(root);
  for (var i = 0; i < children.length; i++) {
    traverse(children[i]);
  }
}

Пожалуйста, поправьте меня, если это не так.

person Sachin Hosmani    schedule 22.06.2014