22 янв. 2013 г.

Какие действия заставляют браузер вычислять layout (делать reflow)

В своей канонической статье Stoyan Stefanov подробно рассмотрел, что такое reflow, как он влияет на плавность работы интерфейса веб-приложения, какими инструментами производить анализ и как минимизировать количество reflow. Он привёл краткий список свойств и методов, вызов которых заставляет браузер вычислять layout (делать reflow):
  • offsetTop, offsetLeft, offsetWidth, offsetHeight
  • scrollTop, scrollLeft, scrollWidth, scrollHeight
  • clientTop, clientLeft, clientWidth, clientHeight
  • currentStyle (IE), getComputedStyle() (остальные браузеры)
Но это только очень краткий список. Как насчёт более обширного перечня?

Как найти полный список для браузера Chromium (практически идентичный для всех браузеров на WebKit), подсказал Tony Gentilcore - в поиске по исходному коду Chromium надо найти вызовы "\->updateLayoutIgnorePendingStylesheets\(\)" (дефис и скобки заэкранированы специально), и проанализировать найденные исходники. Вот список того, что мне удалось идентифицировать (классы JavaScript и методы):

Range

getBoundingClientRect(), getClientRects()

HTMLBodyElement (document.body)

scrollLeft (чтение и запись), scrollTop (чтение и запись), scrollHeight, scrollWidth

Element

scrollIntoView(), scrollIntoViewIfNeeded(), scrollByLines(), scrollByPages(),
offsetLeft, offsetTop, offsetWidth, offsetHeight, offsetParent,
clientLeft, clientTop, clientWidth, clientHeight,
scrollLeft (чтение и запись), scrollTop (чтение и запись), scrollHeight, scrollWidth,
getBoundingClientRect(), getClientRects(), focus(), innerText, outerText, webkitGetRegionFlowRanges()

DOMWindow (window)

scrollX, scrollY, webkitConvertPointFromNodeToPage(), webkitConvertPointFromPageToNode(), scrollBy(), scrollTo()

SVGTextContentElement

getNumberOfChars(), getComputedTextLength(), getSubStringLength(), getStartPositionOfChar(), getEndPositionOfChar(), getExtentOfChar(), getRotationOfChar(), getCharNumAtPosition(), selectSubString()

CSSComputedStyleDeclaration (window.getComputedStyle())

getFontSizeCSSValuePreferringKeyword()
getPropertyCSSValue(), cssText() - получение вычисленного значения стиля, reflow происходит только при выполнении определённых условий

MouseRelatedEvent

computeRelativePosition(), layerX(), layerY(), offsetX(), offsetY() - вычисление координат мышиного события

Остались несопоставленными с вызовами из JavaScript

HTMLFrameElementBase::width(), height() - возможно, ширина и высота фрейма
HTMLImageElement::width(), height() - возможно, ширина и высота изображения
Element::webkitRegionOverset()

HTMLAppletElement::renderWidgetForJSBindings()
HTMLObjectElement::renderWidgetForJSBindings()
HTMLEmbedElement::renderWidgetForJSBindings()

FrameSelection::setSelection()
Page::setPageScaleFactor() - вызывается при изменении масштаба просмотра страницы

Internals::boundingBox(), addTextMatchMarker(), touchEventTargetClientRects()

FrameView::scrollElementToRect(), autoSizeIfEnabled()

FocusController::advanceFocusInDocumentOrder(), advanceFocusDirectionallyInContainer(), advanceFocusDirectionally() - вызываются при установке/перемещении фокуса (с клавиатуры Tab, Shift-Tab)

FatFingers::findIntersectingRegions() - что-то, связанное с тач-интерфейсом на BlackBerry

AccessibilityObject::updateBackingStore()

ReplacementFragment::insertFragmentForTestRendering(), removeUnrenderedTextNodesAtEnds()

SVGLocatable::getBBox() - получение boundingBox для SVGElement
SVGLocatable::computeCTM() - вычисление coordinate transform multiply для SVGElement
SVGPathElement::getBBox()
SVGUseElement::instanceRoot()

EventHandler::handleMousePressEventSingleClick(), handleMousePressEvent(), dispatchMouseEvent() - обработка события нажатия кнопки мыши ("The layout needs to be up to date to determine if an element is focusable")
EventHandler::scrollRecursively(), logicalScrollRecursively()

TextIterator::rangeFromLocationAndLength()

WebKitNamedFlow::overset(), firstEmptyRegionIndex(), getRegionsByContent(), getRegions(), getContent()

isEditablePosition()
previousLinePosition()
EditCommandComposition::unapply(), reapply()
CompositeEditCommand::apply(), appendBlockPlaceholder(), addBlockPlaceholderIfNeeded(), moveParagraphContentsToNewBlockIfNecessary(), moveParagraphs()
IndentOutdentCommand::outdentParagraph()
ApplyStyleCommand::applyBlockStyle(), applyInlineStyle(), applyInlineStyleToNodeRange()
ApplyBlockElementCommand::doApply()
InsertListCommand::listifyParagraph()
Editor::Command::execute()
DeleteSelectionCommand::removeNode(), fixupWhitespace()
InsertIntoTextNodeCommand::doApply()
InsertLineBreakCommand::doApply()
InsertParagraphSeparatorCommand::doApply()

WebViewImpl::scrollFocusedNodeIntoRect() - только если #if ENABLE(GESTURE_EVENTS)

WebNode::isFocusable(), hasNonEmptyBoundingBox()

VisiblePosition::canonicalPosition()

RenderSVGModelObject::checkIntersection(), checkEnclosure()

DeleteButtonController::show()

HTMLTextFormControlElement::textRendererAfterUpdateLayout(), setSelectionRange()

Комментариев нет:

Отправить комментарий