2017-01-18 6 views
2

У меня есть пользовательский элемент, my-el, который в своем шаблоне DOM (теневой корень) содержит элемент slot. На веб-странице я использую my-el, размещая дополнительные элементы между тегами <my-el></my-el>, как показано ниже.Как реагировать на первую краску/макет после распределения начального слота

<my-el> 
    <div class="item"></div> 
    <div class="item"></div> 
    <div class="item"></div> 
    <div class="item"></div> 
</my-el> 

Я намерен измерить Размеры div S', помещенные в my-el, поскольку они находятся в распределенном дерева, , как только (т.е. в первый раз), они отображаются на странице. Согласно spec:

Чтобы назначить slotables, для слота слот с дополнительным флагом подавляют сигнализации (не установлено, если не указано иное), выполнить следующие действия:

  1. Пусть slotables быть результатом поиска слотов для слота.

  2. Если подавить сигнализации флаг не установлен и slotables и назначенные узлы слота не являются идентичными, затем запустить сигнал изменения слота для слота.

...

Если я правильно понял, первое распределение слотов slottables не срабатывает на событие slotchange, так как подавить сигнализации флаг устанавливается, когда слот не выполняется начальное распределение, далее указано в Shadow DOM v1: Self-Contained Web Components. Это означает, что я не могу выполнить начальное измерение дочерних элементов в обратном вызове slotchange. Кроме того, следующий подход не гарантирует, что в этот момент дети будут оказываться:

connectedCallback() { 
    super.connectedCallback(); 

    requestAnimationFrame(() => { 
    // Measure chilren 
    }); 
} 

Вопрос

Как я могу вызвать мои измерения на первый раз они были оказаны после распределения в slot в my-el?

ответ

1

Вы можете определить переменную в своем пользовательском элементе, который будет установлен при первом рендеринге ваших элементов (либо в connectedCallback, либо в событии slotchange).

Затем проверьте значение переменной, чтобы решить, является ли это рендерингом в первый раз.

customElements.define('c-e', class extends HTMLElement 
 
{ 
 
    connectedCallback() 
 
    { 
 
     var sh = this.attachShadow({ mode: 'open' }) 
 
     sh.appendChild(T1.content.cloneNode(true)) 
 
     
 
     sh.querySelector('button').onclick = ev => 
 
      this.appendChild(document.createElement('div')).innerHTML = 'new div' 
 

 
     sh.querySelector('slot').addEventListener('slotchange', ev => 
 
      !len && (len = this.render())) 
 

 
     var len = this.render() 
 
    } 
 

 
    render() 
 
    { 
 
     var count = this.querySelectorAll('div').length 
 
     if (count) 
 
      console.info('%s elem. first rendered in %s', count, this.id) 
 
     return count 
 
    } 
 
})
<c-e id=CE1> 
 
    <div>div 1</div> 
 
    <div>div 2</div> 
 
</c-e> 
 
<c-e id=CE2> 
 
</c-e> 
 

 
<template id=T1> 
 
    <style> 
 
    :host { 
 
     display: inline-flex; 
 
     flex-direction: column; 
 
     width: 150px; 
 
     border: 1px solid lightblue; 
 
     min-height: 4em; 
 
     margin: 5px; 
 
     background: #f7f7f7; 
 
    } 
 
    </style> 
 
    <div> 
 
    <button>add div</button> 
 
    </div> 
 
    <slot> 
 
    </slot> 
 
</template>

+1

Это не _quite_ ответить на этот вопрос, но близко. Я ищу точку, в которой я могу ** гарантировать **, что элементы будут отображаться в DOM. В вашем примере выполнение измерений в 'connectedCallback' работает, но так ли это, потому что это простой пример? Другими словами, как мы можем гарантировать рендеринг? (обратите внимание, что «рендеринг гарантии» не подразумевает «принудительный рендеринг») – WoodyWoodsta

+1

Рендеринг синхронный, поэтому я не вижу смысла.Может быть, вы должны привести конкретный пример, когда рендеринг не гарантируется в connectedCallback. Случаи использования разных вариантов уже обсуждались (http://stackoverflow.com/q/40378115, http://stackoverflow.com/q/36187227, http://stackoverflow.com/q/35805252, http: // stackoverflow. com/q/33602247) – Supersharp

+0

У меня был хороший взгляд на вопросы в ссылках. Я также собрал более полную скрипку для экспериментов. Похоже, что это действительно синхронно, так как пока вы измеряете после ввода шаблона в DOM, измерение должно быть оправданным? Я использую [Polymer] (https://www.polymer-project.org/1.0/) для разработки моих компонентов и приложений, а их жизненный цикл рендеринга элементов сложнее. Я надеялся, что существует платформа, а не эффект, созданный каркасной архитектурой. Так что это, если до API фреймворка! Спасибо за помощь! – WoodyWoodsta