use event delegation for better perf

This commit is contained in:
Nolan Lawson 2018-02-10 11:30:13 -08:00
parent 08c19691a9
commit e6304cbbf3
2 changed files with 68 additions and 2 deletions

View file

@ -1,6 +1,9 @@
<article class="status-article {{getClasses(originalStatus, timelineType, isStatusInOwnThread)}}"
tabindex="0" on:click="onClickOrKeydown(event)" on:keydown="onClickOrKeydown(event)"
aria-posinset="{{index}}" aria-setsize="{{length}}"
tabindex="0"
delegate-click-key="{{delegateKey}}"
delegate-keydown-key="{{delegateKey}}"
aria-posinset="{{index}}"
aria-setsize="{{length}}"
aria-label="Status by {{originalStatus.account.display_name || originalStatus.account.username}}"
on:recalculateHeight>
{{#if (notification && (notification.type === 'reblog' || notification.type === 'favourite')) || status.reblog}}
@ -87,8 +90,20 @@
import { store } from '../../_store/store'
import identity from 'lodash/identity'
import { goto } from 'sapper/runtime.js'
import { registerDelegate, unregisterDelegate } from '../../_utils/delegate'
export default {
oncreate() {
let delegateKey = this.get('delegateKey')
let onClickOrKeydown = this.onClickOrKeydown.bind(this)
registerDelegate('click', delegateKey, onClickOrKeydown)
registerDelegate('keydown', delegateKey, onClickOrKeydown)
},
ondestroy() {
let delegateKey = this.get('delegateKey')
unregisterDelegate('click', delegateKey)
unregisterDelegate('keydown', delegateKey)
},
components: {
StatusSidebar,
StatusHeader,
@ -132,6 +147,7 @@
computed: {
originalStatus: (status) => status.reblog ? status.reblog : status,
statusId: (originalStatus) => originalStatus.id,
delegateKey: (statusId, timelineType, timelineValue) => `status-${timelineType}-${timelineValue}-${statusId}`,
contextualStatusId: ($currentInstance, timelineType, timelineValue, status, notification) => {
return `${$currentInstance}/${timelineType}/${timelineValue}/${notification ? notification.id : ''}/${status.id}`
},

50
routes/_utils/delegate.js Normal file
View file

@ -0,0 +1,50 @@
// Delegate certain events to the global document for perf purposes.
import { mark, stop } from './marks'
const callbacks = {}
if (process.browser && process.env.NODE_ENV !== 'production') {
window.delegateCallbacks = callbacks
}
function onEvent(e) {
let { type, keyCode, target } = e
if (!(type === 'click' || (type === 'keydown' && keyCode === 13))) {
// we're not interested in any non-click or non-Enter events
return
}
mark('delegate onEvent')
let attr = `delegate-${type}-key`
let key
let element = target
while (element) {
if ((key = element.getAttribute(attr))) {
break
}
element = element.parentElement
}
if (key && callbacks[type] && callbacks[type][key]) {
callbacks[type][key](e)
}
stop('delegate onEvent')
}
export function registerDelegate(type, key, callback) {
mark('delegate registerDelegate')
callbacks[type] = callbacks[type] || {}
callbacks[type][key] = callback
stop('delegate registerDelegate')
}
export function unregisterDelegate(type, key) {
mark('delegate unregisterDelegate')
callbacks[type] = callbacks[type] || {}
delete callbacks[type][key]
stop('delegate unregisterDelegate')
}
if (process.browser) {
document.addEventListener('click', onEvent)
document.addEventListener('keydown', onEvent)
}