replace getBoundingClientRect() with offset/scrollTop & clientHeight
as they are an order of magnitude faster in most browsers, getBoundingClientRect() tends to cause relayout.
This commit is contained in:
parent
ecb074862e
commit
03784e586c
1 changed files with 26 additions and 19 deletions
|
@ -576,9 +576,10 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
const scrollNode = this._getScrollNode();
|
const scrollNode = this._getScrollNode();
|
||||||
const wrapperRect = ReactDOM.findDOMNode(this).getBoundingClientRect();
|
const scrollBottom = scrollNode.scrollTop + scrollNode.clientHeight;
|
||||||
const boundingRect = node.getBoundingClientRect();
|
|
||||||
const scrollDelta = boundingRect.bottom + pixelOffset - wrapperRect.bottom;
|
const nodeBottom = node.offsetTop + node.clientHeight;
|
||||||
|
const scrollDelta = nodeBottom + pixelOffset - scrollBottom;
|
||||||
|
|
||||||
debuglog("ScrollPanel: scrolling to token '" + scrollToken + "'+" +
|
debuglog("ScrollPanel: scrolling to token '" + scrollToken + "'+" +
|
||||||
pixelOffset + " (delta: "+scrollDelta+")");
|
pixelOffset + " (delta: "+scrollDelta+")");
|
||||||
|
@ -595,37 +596,43 @@ module.exports = React.createClass({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const scrollNode = this._getScrollNode();
|
||||||
|
const scrollBottom = scrollNode.scrollTop + scrollNode.clientHeight;
|
||||||
|
|
||||||
const itemlist = this.refs.itemlist;
|
const itemlist = this.refs.itemlist;
|
||||||
const wrapperRect = ReactDOM.findDOMNode(this).getBoundingClientRect();
|
|
||||||
const messages = itemlist.children;
|
const messages = itemlist.children;
|
||||||
let newScrollState = null;
|
let node = null;
|
||||||
|
let nodeBottom;
|
||||||
|
|
||||||
|
// TODO: change this to not use getBoundingClientRect and save the domnode
|
||||||
for (let i = messages.length-1; i >= 0; --i) {
|
for (let i = messages.length-1; i >= 0; --i) {
|
||||||
const node = messages[i];
|
if (!messages[i].dataset.scrollTokens) {
|
||||||
if (!node.dataset.scrollTokens) continue;
|
continue;
|
||||||
|
}
|
||||||
|
node = messages[i];
|
||||||
|
|
||||||
const boundingRect = node.getBoundingClientRect();
|
nodeBottom = node.offsetTop + node.clientHeight;
|
||||||
newScrollState = {
|
|
||||||
stuckAtBottom: false,
|
|
||||||
trackedScrollToken: node.dataset.scrollTokens.split(',')[0],
|
|
||||||
pixelOffset: wrapperRect.bottom - boundingRect.bottom,
|
|
||||||
};
|
|
||||||
// If the bottom of the panel intersects the ClientRect of node, use this node
|
// If the bottom of the panel intersects the ClientRect of node, use this node
|
||||||
// as the scrollToken.
|
// as the scrollToken.
|
||||||
// If this is false for the entire for-loop, we default to the last node
|
// If this is false for the entire for-loop, we default to the last node
|
||||||
// (which is why newScrollState is set on every iteration).
|
// (which is why newScrollState is set on every iteration).
|
||||||
if (boundingRect.top < wrapperRect.bottom) {
|
if (nodeBottom >= scrollBottom) {
|
||||||
// Use this node as the scrollToken
|
// Use this node as the scrollToken
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// This is only false if there were no nodes with `node.dataset.scrollTokens` set.
|
|
||||||
if (newScrollState) {
|
if (!node) {
|
||||||
this.scrollState = newScrollState;
|
|
||||||
debuglog("ScrollPanel: saved scroll state", this.scrollState);
|
|
||||||
} else {
|
|
||||||
debuglog("ScrollPanel: unable to save scroll state: found no children in the viewport");
|
debuglog("ScrollPanel: unable to save scroll state: found no children in the viewport");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debuglog("ScrollPanel: saved scroll state", this.scrollState);
|
||||||
|
this.scrollState = {
|
||||||
|
stuckAtBottom: false,
|
||||||
|
trackedScrollToken: node.dataset.scrollTokens.split(',')[0],
|
||||||
|
pixelOffset: scrollBottom - nodeBottom,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
_restoreSavedScrollState: function() {
|
_restoreSavedScrollState: function() {
|
||||||
|
|
Loading…
Reference in a new issue