mirror of
https://github.com/liriliri/eruda.git
synced 2026-03-20 09:38:37 +08:00
perf(console): rendering
This commit is contained in:
@@ -41,7 +41,7 @@ export default class Console extends Tool {
|
|||||||
}
|
}
|
||||||
show() {
|
show() {
|
||||||
super.show()
|
super.show()
|
||||||
this._logger.restoreScroll()
|
this._logger.renderViewport()
|
||||||
}
|
}
|
||||||
overrideConsole() {
|
overrideConsole() {
|
||||||
const origConsole = (this._origConsole = {})
|
const origConsole = (this._origConsole = {})
|
||||||
|
|||||||
@@ -31,10 +31,11 @@ import {
|
|||||||
trim,
|
trim,
|
||||||
lowerCase,
|
lowerCase,
|
||||||
keys,
|
keys,
|
||||||
$
|
$,
|
||||||
|
Emitter
|
||||||
} from '../lib/util'
|
} from '../lib/util'
|
||||||
|
|
||||||
export default class Log {
|
export default class Log extends Emitter {
|
||||||
constructor({
|
constructor({
|
||||||
type = 'log',
|
type = 'log',
|
||||||
args = [],
|
args = [],
|
||||||
@@ -44,6 +45,8 @@ export default class Log {
|
|||||||
displayHeader = false,
|
displayHeader = false,
|
||||||
ignoreFilter = false
|
ignoreFilter = false
|
||||||
}) {
|
}) {
|
||||||
|
super()
|
||||||
|
|
||||||
this.type = type
|
this.type = type
|
||||||
this.group = group
|
this.group = group
|
||||||
this.targetGroup = targetGroup
|
this.targetGroup = targetGroup
|
||||||
@@ -137,8 +140,12 @@ export default class Log {
|
|||||||
isAttached() {
|
isAttached() {
|
||||||
return !!this.el.parentNode
|
return !!this.el.parentNode
|
||||||
}
|
}
|
||||||
updateHeight() {
|
updateHeight(silent = true) {
|
||||||
this.height = this.el.offsetHeight
|
const height = this.el.offsetHeight
|
||||||
|
if (this.height !== height) {
|
||||||
|
this.height = this.el.offsetHeight
|
||||||
|
if (!silent) this.emit('updateHeight')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
html() {
|
html() {
|
||||||
return this.el.outerHTML
|
return this.el.outerHTML
|
||||||
@@ -193,7 +200,7 @@ export default class Log {
|
|||||||
if ($json.hasClass('eruda-hidden')) {
|
if ($json.hasClass('eruda-hidden')) {
|
||||||
if ($json.data('init') !== 'true') {
|
if ($json.data('init') !== 'true') {
|
||||||
const jsonViewer = new JsonViewer(src, $json)
|
const jsonViewer = new JsonViewer(src, $json)
|
||||||
jsonViewer.on('change', () => this.updateHeight())
|
jsonViewer.on('change', () => this.updateHeight(false))
|
||||||
$json.data('init', 'true')
|
$json.data('init', 'true')
|
||||||
}
|
}
|
||||||
$json.rmClass('eruda-hidden')
|
$json.rmClass('eruda-hidden')
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import {
|
|||||||
toArr,
|
toArr,
|
||||||
keys,
|
keys,
|
||||||
last,
|
last,
|
||||||
debounce
|
throttle
|
||||||
} from '../lib/util'
|
} from '../lib/util'
|
||||||
|
|
||||||
let id = 0
|
let id = 0
|
||||||
@@ -53,6 +53,8 @@ export default class Logger extends Emitter {
|
|||||||
this._isAtBottom = true
|
this._isAtBottom = true
|
||||||
this._groupStack = new Stack()
|
this._groupStack = new Stack()
|
||||||
|
|
||||||
|
this.renderViewport = throttle(force => this._renderViewport(force), 16)
|
||||||
|
|
||||||
// https://developers.google.cn/web/tools/chrome-devtools/console/utilities
|
// https://developers.google.cn/web/tools/chrome-devtools/console/utilities
|
||||||
this._global = {
|
this._global = {
|
||||||
copy(value) {
|
copy(value) {
|
||||||
@@ -79,9 +81,6 @@ export default class Logger extends Emitter {
|
|||||||
|
|
||||||
this._bindEvent()
|
this._bindEvent()
|
||||||
}
|
}
|
||||||
restoreScroll() {
|
|
||||||
if (this._isAtBottom) this.scrollToBottom()
|
|
||||||
}
|
|
||||||
renderAsync(flag) {
|
renderAsync(flag) {
|
||||||
this._asyncRender = flag
|
this._asyncRender = flag
|
||||||
}
|
}
|
||||||
@@ -281,8 +280,6 @@ export default class Logger extends Emitter {
|
|||||||
this._attachLog(logs[i])
|
this._attachLog(logs[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
this.scrollToBottom()
|
|
||||||
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
insert(type, args) {
|
insert(type, args) {
|
||||||
@@ -295,17 +292,6 @@ export default class Logger extends Emitter {
|
|||||||
|
|
||||||
this._handleAsyncList()
|
this._handleAsyncList()
|
||||||
}
|
}
|
||||||
isAtBottom() {
|
|
||||||
const { scrollTop, scrollHeight, offsetHeight } = this._container
|
|
||||||
|
|
||||||
// invisible
|
|
||||||
if (offsetHeight !== 0) {
|
|
||||||
this._isAtBottom = scrollTop === scrollHeight - offsetHeight
|
|
||||||
return this._isAtBottom
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
insertSync(type, args) {
|
insertSync(type, args) {
|
||||||
const logs = this._logs
|
const logs = this._logs
|
||||||
const groupStack = this._groupStack
|
const groupStack = this._groupStack
|
||||||
@@ -318,8 +304,6 @@ export default class Logger extends Emitter {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
const isAtBottom = this.isAtBottom()
|
|
||||||
|
|
||||||
const options = isStr(type) ? { type, args } : type
|
const options = isStr(type) ? { type, args } : type
|
||||||
if (groupStack.size > 0) {
|
if (groupStack.size > 0) {
|
||||||
options.group = groupStack.peek()
|
options.group = groupStack.peek()
|
||||||
@@ -342,6 +326,7 @@ export default class Logger extends Emitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let log = new Log(options)
|
let log = new Log(options)
|
||||||
|
log.on('updateHeight', () => this.renderViewport())
|
||||||
|
|
||||||
const lastLog = this._lastLog
|
const lastLog = this._lastLog
|
||||||
if (
|
if (
|
||||||
@@ -371,16 +356,8 @@ export default class Logger extends Emitter {
|
|||||||
|
|
||||||
this.emit('insert', log)
|
this.emit('insert', log)
|
||||||
|
|
||||||
if (isAtBottom) this.scrollToBottom()
|
|
||||||
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
scrollToBottom() {
|
|
||||||
const container = this._container
|
|
||||||
const { scrollHeight, offsetHeight } = container
|
|
||||||
|
|
||||||
container.scrollTop = scrollHeight - offsetHeight
|
|
||||||
}
|
|
||||||
toggleGroup(log) {
|
toggleGroup(log) {
|
||||||
const { targetGroup } = log
|
const { targetGroup } = log
|
||||||
targetGroup.collapsed ? this._openGroup(log) : this._collapseGroup(log)
|
targetGroup.collapsed ? this._openGroup(log) : this._collapseGroup(log)
|
||||||
@@ -394,6 +371,7 @@ export default class Logger extends Emitter {
|
|||||||
this._$bottomSpace.css({ height })
|
this._$bottomSpace.css({ height })
|
||||||
}
|
}
|
||||||
_updateLogHeight(log) {
|
_updateLogHeight(log) {
|
||||||
|
if (this._fakeEl.offsetParent === null) return
|
||||||
if (!log.isAttached()) {
|
if (!log.isAttached()) {
|
||||||
this._fakeEl.appendChild(log.el)
|
this._fakeEl.appendChild(log.el)
|
||||||
log.updateHeight()
|
log.updateHeight()
|
||||||
@@ -408,7 +386,7 @@ export default class Logger extends Emitter {
|
|||||||
const idx = displayLogs.indexOf(log)
|
const idx = displayLogs.indexOf(log)
|
||||||
if (idx > -1) {
|
if (idx > -1) {
|
||||||
displayLogs.splice(idx, 1)
|
displayLogs.splice(idx, 1)
|
||||||
this._renderViewport()
|
this.renderViewport()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Binary search
|
// Binary search
|
||||||
@@ -419,14 +397,14 @@ export default class Logger extends Emitter {
|
|||||||
|
|
||||||
if (displayLogs.length === 0) {
|
if (displayLogs.length === 0) {
|
||||||
displayLogs.push(log)
|
displayLogs.push(log)
|
||||||
this._renderViewport()
|
this.renderViewport()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const lastDisplayLog = last(displayLogs)
|
const lastDisplayLog = last(displayLogs)
|
||||||
if (log.id > lastDisplayLog.id) {
|
if (log.id > lastDisplayLog.id) {
|
||||||
displayLogs.push(log)
|
displayLogs.push(log)
|
||||||
this._renderViewport()
|
this.renderViewport()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,7 +435,7 @@ export default class Logger extends Emitter {
|
|||||||
displayLogs.splice(middleIdx, 0, log)
|
displayLogs.splice(middleIdx, 0, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
this._renderViewport()
|
this.renderViewport()
|
||||||
}
|
}
|
||||||
_handleAsyncList() {
|
_handleAsyncList() {
|
||||||
const asyncList = this._asyncList
|
const asyncList = this._asyncList
|
||||||
@@ -467,7 +445,7 @@ export default class Logger extends Emitter {
|
|||||||
this._asyncTimer = setTimeout(() => {
|
this._asyncTimer = setTimeout(() => {
|
||||||
this._asyncTimer = null
|
this._asyncTimer = null
|
||||||
let done = false
|
let done = false
|
||||||
for (let i = 0; i < 25; i++) {
|
for (let i = 0; i < 20; i++) {
|
||||||
const item = asyncList.shift()
|
const item = asyncList.shift()
|
||||||
if (!item) {
|
if (!item) {
|
||||||
done = true
|
done = true
|
||||||
@@ -476,7 +454,7 @@ export default class Logger extends Emitter {
|
|||||||
this.insertSync(item[0], item[1])
|
this.insertSync(item[0], item[1])
|
||||||
}
|
}
|
||||||
if (!done) this._handleAsyncList()
|
if (!done) this._handleAsyncList()
|
||||||
}, 25)
|
}, 15)
|
||||||
}
|
}
|
||||||
_injectGlobal() {
|
_injectGlobal() {
|
||||||
each(this._global, (val, name) => {
|
each(this._global, (val, name) => {
|
||||||
@@ -584,35 +562,69 @@ export default class Logger extends Emitter {
|
|||||||
self._openGroup($el.get(0).log)
|
self._openGroup($el.get(0).log)
|
||||||
})
|
})
|
||||||
|
|
||||||
const renderViewport = debounce(() => this._renderViewport(), 15)
|
this._$container.on('scroll', () => this.renderViewport(false))
|
||||||
this._$container.on('scroll', renderViewport)
|
|
||||||
}
|
}
|
||||||
_renderViewport() {
|
_renderViewport(force = true) {
|
||||||
const { scrollTop, offsetHeight } = this._container
|
const container = this._container
|
||||||
const top = scrollTop
|
if (container.offsetParent === null) return
|
||||||
const bottom = scrollTop + offsetHeight
|
const { scrollTop, offsetHeight } = container
|
||||||
|
let top = scrollTop
|
||||||
|
let bottom = scrollTop + offsetHeight
|
||||||
|
|
||||||
|
if (!force) {
|
||||||
|
if (
|
||||||
|
this._topSpaceHeight < top &&
|
||||||
|
this._topSpaceHeight + this._el.offsetHeight > bottom
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const displayLogs = this._displayLogs
|
const displayLogs = this._displayLogs
|
||||||
|
const tolerance = 1000
|
||||||
|
top -= tolerance
|
||||||
|
bottom += tolerance
|
||||||
|
|
||||||
let topSpaceHeight = 0
|
let topSpaceHeight = 0
|
||||||
let bottomSpaceHeight = 0
|
let bottomSpaceHeight = 0
|
||||||
let currentHeight = 0
|
let currentHeight = 0
|
||||||
|
|
||||||
this._$el.html('')
|
this._$el.html('')
|
||||||
|
const frag = document.createDocumentFragment()
|
||||||
for (let i = 0, len = displayLogs.length; i < len; i++) {
|
for (let i = 0, len = displayLogs.length; i < len; i++) {
|
||||||
const { el, height } = displayLogs[i]
|
const log = displayLogs[i]
|
||||||
|
const { el } = log
|
||||||
|
let { height } = log
|
||||||
|
if (height === 0) {
|
||||||
|
this._updateLogHeight(log)
|
||||||
|
height = log.height
|
||||||
|
}
|
||||||
|
|
||||||
if (currentHeight > bottom) {
|
if (currentHeight > bottom) {
|
||||||
bottomSpaceHeight += height
|
bottomSpaceHeight += height
|
||||||
} else if (currentHeight + height > top) {
|
} else if (currentHeight + height > top) {
|
||||||
this._el.appendChild(el)
|
frag.appendChild(el)
|
||||||
} else if (currentHeight < top) {
|
} else if (currentHeight < top) {
|
||||||
topSpaceHeight += height
|
topSpaceHeight += height
|
||||||
}
|
}
|
||||||
|
|
||||||
currentHeight += height
|
currentHeight += height
|
||||||
}
|
}
|
||||||
|
this._el.appendChild(frag)
|
||||||
|
|
||||||
this._updateTopSpace(topSpaceHeight)
|
this._updateTopSpace(topSpaceHeight)
|
||||||
this._updateBottomSpace(bottomSpaceHeight)
|
this._updateBottomSpace(bottomSpaceHeight)
|
||||||
|
|
||||||
|
container.scrollTop = scrollTop
|
||||||
|
|
||||||
|
const scrollHeight = container.scrollHeight
|
||||||
|
if (this._isAtBottom) {
|
||||||
|
container.scrollTop = scrollHeight - offsetHeight
|
||||||
|
this._isAtBottom = true
|
||||||
|
} else if (scrollHeight === offsetHeight) {
|
||||||
|
this._isAtBottom = true
|
||||||
|
} else if (container.scrollTop === scrollHeight - offsetHeight) {
|
||||||
|
this._isAtBottom = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user