diff --git a/src/compiler/compile/render_dom/Block.ts b/src/compiler/compile/render_dom/Block.ts index 164e938674..2e2568d156 100644 --- a/src/compiler/compile/render_dom/Block.ts +++ b/src/compiler/compile/render_dom/Block.ts @@ -4,6 +4,7 @@ import { b, x } from 'code-red'; import { Node, Identifier, ArrayPattern } from 'estree'; import { is_head } from './wrappers/shared/is_head'; import { regex_double_quotes } from '../../utils/patterns'; +import { Expression } from 'estree'; export interface Bindings { object: Identifier; @@ -58,6 +59,7 @@ export default class Block { destroy: Array; }; + event_updaters: ({condition:Expression, snippet:Node, index:number})[] = []; event_listeners: Node[] = []; maintain_context: boolean; @@ -481,6 +483,15 @@ export default class Block { ` ); + if (this.event_updaters.length === 1) { + const {condition, snippet} = this.event_updaters[0]; + this.chunks.update.push(b` + if (${condition}) { + ${dispose}.swap(${snippet}) + }` + ); + } + this.chunks.destroy.push( b`${dispose}();` ); @@ -494,6 +505,14 @@ export default class Block { } `); + for (const {condition, snippet, index} of this.event_updaters) { + this.chunks.update.push(b` + if (${condition}) { + ${dispose}[${index}].swap(${snippet}) + }` + ); + } + this.chunks.destroy.push( b`@run_all(${dispose});` ); diff --git a/src/compiler/compile/render_dom/wrappers/Element/EventHandler.ts b/src/compiler/compile/render_dom/wrappers/Element/EventHandler.ts index 7fda7672a4..99488ad850 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/EventHandler.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/EventHandler.ts @@ -1,9 +1,8 @@ import EventHandler from '../../../nodes/EventHandler'; import Wrapper from '../shared/Wrapper'; import Block from '../../Block'; -import { x, p, b } from 'code-red'; +import { x, p } from 'code-red'; import { Expression } from 'estree'; -import { sanitize } from '../../../../utils/names'; const TRUE = x`true`; const FALSE = x`false`; @@ -67,17 +66,12 @@ export default class EventHandlerWrapper { } if (this.node.reassigned) { - const handle = this.node.component.get_unique_name(`${sanitize(this.node.name)}_handle`); - block.add_variable(handle); - + const index = block.event_listeners.length; const condition = block.renderer.dirty(this.node.expression.dynamic_dependencies()); - block.chunks.update.push(b` - if (${condition}) { - ${handle}.swap(${snippet}) - }`); + block.event_updaters.push({condition, snippet, index}); block.event_listeners.push( - x`${handle} = @listen_swap(${snippet}, (h)=> ${listen}(${target}, "${this.node.name}", h, ${args}))` + x`@listen_swap(${snippet}, (h)=> ${listen}(${target}, "${this.node.name}", h, ${args}))` ); } else { block.event_listeners.push( diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 1078daf539..abdc28d8ec 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -264,16 +264,16 @@ export function wrap_handler(handler: EventListenerOrEventListenerObject, wrappe return result; } -export function listen(node: EventTarget, event: string, handler: EventListenerOrEventListenerObject|null|undefined, options?: boolean | AddEventListenerOptions | EventListenerOptions, wrappers?: Function[]) { +export function listen(node: EventTarget, event: string, handler: EventListenerOrEventListenerObject|null|undefined|false, options?: boolean | AddEventListenerOptions | EventListenerOptions, wrappers?: Function[]) { if (handler) { - handler = wrap_handler(handler, wrappers); - node.addEventListener(event, handler, options); - return () => node.removeEventListener(event, handler, options); + const h = wrap_handler(handler, wrappers); + node.addEventListener(event, h, options); + return () => node.removeEventListener(event, h, options); } return noop; } -export function listen_swap(handler: EventListenerOrEventListenerObject|null|undefined, factory: (handler:EventListenerOrEventListenerObject) => Function) { +export function listen_swap(handler: EventListenerOrEventListenerObject|null|undefined|false, factory: (handler:EventListenerOrEventListenerObject|null|undefined|false) => Function) { let disposeHandle: Function = factory(handler); const dispose = () => { disposeHandle(); diff --git a/src/runtime/internal/lifecycle.ts b/src/runtime/internal/lifecycle.ts index b5a29688a7..b8d2dbd083 100644 --- a/src/runtime/internal/lifecycle.ts +++ b/src/runtime/internal/lifecycle.ts @@ -231,7 +231,7 @@ export function bubble(component: SvelteComponent, listen_func: Function, node: }); } -export function listen_comp(comp: SvelteComponent, event: string, handler: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | EventListenerOptions, wrappers?: Function[]) { +export function listen_comp(comp: SvelteComponent, event: string, handler: EventListenerOrEventListenerObject|null|undefined|false, options?: boolean | AddEventListenerOptions | EventListenerOptions, wrappers?: Function[]) { if (handler) { return comp.$on(event, wrap_handler(handler, wrappers), options); }