perf(ivy): attempt to coalesce listeners only in presence of directives (#29859)
PR Close #29859
This commit is contained in:
parent
d1d0f4a1ad
commit
6a1441f727
|
@ -14,7 +14,7 @@ import {GlobalTargetResolver, RElement, Renderer3, isProceduralRenderer} from '.
|
|||
import {CLEANUP, FLAGS, LView, LViewFlags, RENDERER, TVIEW} from '../interfaces/view';
|
||||
import {assertNodeOfPossibleTypes} from '../node_assert';
|
||||
import {getLView, getPreviousOrParentTNode} from '../state';
|
||||
import {getComponentViewByIndex, getNativeByTNode, unwrapRNode} from '../util/view_utils';
|
||||
import {getComponentViewByIndex, getNativeByTNode, hasDirectives, unwrapRNode} from '../util/view_utils';
|
||||
import {BindingDirection, generatePropertyAliases, getCleanup, handleError, loadComponentRenderer, markViewDirty} from './shared';
|
||||
|
||||
/**
|
||||
|
@ -132,12 +132,16 @@ function listenerInternal(
|
|||
// In order to have just one native event handler in presence of multiple handler functions,
|
||||
// we just register a first handler function as a native event listener and then chain
|
||||
// (coalesce) other handler functions on top of the first native handler function.
|
||||
//
|
||||
let existingListener = null;
|
||||
// Please note that the coalescing described here doesn't happen for events specifying an
|
||||
// alternative target (ex. (document:click)) - this is to keep backward compatibility with the
|
||||
// view engine.
|
||||
const existingListener =
|
||||
eventTargetResolver ? null : findExistingListener(lView, eventName, tNode.index);
|
||||
// Also, we don't have to search for existing listeners is there are no directives
|
||||
// matching on a given node as we can't register multiple event handlers for the same event in
|
||||
// a template (this would mean having duplicate attributes).
|
||||
if (!eventTargetResolver && hasDirectives(tNode)) {
|
||||
existingListener = findExistingListener(lView, eventName, tNode.index);
|
||||
}
|
||||
if (existingListener !== null) {
|
||||
// Attach a new listener at the head of the coalesced listeners list.
|
||||
(<any>listenerFn).__ngNextListenerFn__ = (<any>existingListener).__ngNextListenerFn__;
|
||||
|
|
|
@ -131,6 +131,13 @@ export function getNativeByTNode(tNode: TNode, hostView: LView): RNode {
|
|||
return unwrapRNode(hostView[tNode.index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function that returns `true` if a given `TNode` has any matching directives.
|
||||
*/
|
||||
export function hasDirectives(tNode: TNode): boolean {
|
||||
return tNode.directiveEnd > tNode.directiveStart;
|
||||
}
|
||||
|
||||
export function getTNode(index: number, view: LView): TNode {
|
||||
ngDevMode && assertGreaterThan(index, -1, 'wrong index for TNode');
|
||||
ngDevMode && assertLessThan(index, view[TVIEW].data.length, 'wrong index for TNode');
|
||||
|
|
|
@ -848,6 +848,9 @@
|
|||
{
|
||||
"name": "hasClassInput"
|
||||
},
|
||||
{
|
||||
"name": "hasDirectives"
|
||||
},
|
||||
{
|
||||
"name": "hasParentInjector"
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue