import * as React from 'react'
import * as ReactDOM from 'react-dom'
import * as PropTypes from 'prop-types'
import { IDebugInfo } from 'dob'
import * as S from './debug-box.style'
import { Props, State } from './debug-box.type'
import { RenderTo } from '../../components/render-to/src'
import { DebugLine } from '../../tool-box/debug-line/debug-line.component'
/**
* 根据 render 次数渲染颜色
*/
function renderCount(count: number) {
let level = 'normal'
if (count < 5) {
level = 'normal'
}
if (count >= 5 && count < 10) {
level = 'frequently'
}
if (count >= 10 && count < 20) {
level = 'warning'
}
if (count >= 20) {
level = 'danger'
}
return {count}
}
export class DebugBox extends React.PureComponent{
static defaultProps = new Props()
public state = new State()
private restartAnimationTimeout: any = null
private showCountTimeout: any = null
/**
* 对应元素 dom
*/
private realChildDOM: HTMLElement = undefined
/**
* 高亮 box dom
*/
private highLightBoxDOM: HTMLElement = null
/**
* 保留全部 debugIds
*/
private allDebugIds = new Set()
/**
* 鼠标是否在元素内
*/
private isMouseEnter = false
private isMount = false
public componentWillMount() {
this.isMount = true
this.props.dyDebug.event.on('focusDebug', this.handleFocusDebug)
this.props.dyDebug.event.on('unFocusDebug', this.handleUnFocusDebug)
}
public componentWillUnmount() {
this.isMount = false
this.props.dyDebug.event.off('focusDebug', this.handleFocusDebug)
this.props.dyDebug.event.off('unFocusDebug', this.handleUnFocusDebug)
}
public render() {
return (
{
this.highLightBoxDOM = ReactDOM.findDOMNode(ref) as HTMLElement
}}
style={{
left: this.state.left,
top: this.state.top,
width: this.state.width,
height: this.state.height
}}
/>
{this.renderDebug()}
)
}
/**
* 外部调用 设置 realChildDOM
*/
public setRealChildDOM = (element: HTMLElement) => {
this.realChildDOM = element
}
/**
* 外部调用 增加一个 debugId
*/
public addDebugId = (debugId: number) => {
if (this.allDebugIds.has(debugId)) {
// 防止死循环
return
}
if (!this.realChildDOM) {
return
}
this.allDebugIds.add(debugId)
const realChildRect = this.realChildDOM.getBoundingClientRect()
this.setState(state => {
const newDebugIds = state.debugIds.slice()
newDebugIds.push(debugId)
return {
renderCount: state.renderCount + 1,
showCount: true,
debugIds: newDebugIds,
left: realChildRect.left,
top: realChildRect.top,
width: realChildRect.width,
height: realChildRect.height
}
})
this.highlight()
}
private renderDebug = () => {
if (this.state.showDetail) {
return (
{this.renderDebugDetail()}
)
} else {
return (
{this.renderDebugSimple()}
)
}
}
private renderDebugSimple = () => {
if (!this.state.showCount) {
return null
}
return (
{
this.isMouseEnter = true
this.setState({
showDetail: true
})
}}
>
{renderCount(this.state.renderCount)}
)
}
private renderDebugDetail = () => {
if (!this.state.showCount) {
return null
}
return (
{
this.isMouseEnter = false
this.setState({
showDetail: false
})
}}
>
dob rerender:
{renderCount(this.state.renderCount)}
{this.renderActionList()}
)
}
private renderActionList = () => {
const debugInfos = this.props.dyDebug.debugInfoMap as Map
return this.state.debugIds
.filter(debugId => debugId !== undefined && debugId !== null)
.filter(debugId => debugInfos.has(debugId))
.sort((left, right) => right - left)
.map((debugId, index) => {
return (
{
this.props.dyDebug.event.emit('toggleActionDetail', debugId)
}}
key={index}
onMouseEnter={() => {
this.props.dyDebug.event.emit('focusActionDetail', debugId)
}}
onMouseLeave={() => {
this.props.dyDebug.event.emit('unFocusActionDetail', debugId)
}}
debugInfo={debugInfos.get(debugId)}
dyDebug={this.props.dyDebug}
/>
)
})
}
private handleFocusDebug = (debugId: number) => {
if (!this.allDebugIds.has(debugId)) {
return
}
this.highlight()
}
private handleUnFocusDebug = (debugId: number) => {
if (!this.allDebugIds.has(debugId)) {
return
}
this.removeHighlight()
}
/**
* 立刻闪一下
*/
private highlight = () => {
if (!this.realChildDOM) {
return
}
// 更新位置
const realChildRect = this.realChildDOM.getBoundingClientRect()
this.setState({
left: realChildRect.left,
top: realChildRect.top,
width: realChildRect.width,
height: realChildRect.height
})
this.highLightBoxDOM.classList.remove('dob-debug-animation')
clearTimeout(this.restartAnimationTimeout)
this.restartAnimationTimeout = setTimeout(() => {
if (!this.isMount) {
return
}
this.highLightBoxDOM.classList.add('dob-debug-animation')
this.removeCountLater()
})
}
/**
* 立刻移除闪动
*/
private removeHighlight = () => {
if (!this.realChildDOM) {
return
}
this.highLightBoxDOM.classList.remove('dob-debug-animation')
this.removeCountLater(0)
}
/**
* 稍后移除 count
*/
private removeCountLater = (timeout = 3000) => {
clearTimeout(this.showCountTimeout)
this.showCountTimeout = setTimeout(() => {
// 如果鼠标还在元素上,再暂缓移除
if (this.isMouseEnter) {
this.removeCountLater(500)
return
}
if (!this.isMount) {
return
}
this.setState(state => {
return {
renderCount: 0,
showCount: false,
debugIds: []
}
})
}, timeout)
}
}