0
0
mirror of https://github.com/sveltejs/svelte.git synced 2024-12-01 17:30:59 +01:00

component events

This commit is contained in:
Rich-Harris 2016-11-21 17:33:29 -05:00
parent abd8b77106
commit 24e768e4d2
8 changed files with 87 additions and 28 deletions

View File

@ -272,12 +272,13 @@ export default function generate ( parsed, template, options = {} ) {
};
this.on = function on ( eventName, handler ) {
callbacks[ eventName ] || ( callbacks[ eventName ] = [] ).push( handler );
const handlers = callbacks[ eventName ] || ( callbacks[ eventName ] = [] );
handlers.push( handler );
return {
cancel: function () {
const index = callbacks.indexOf( handler );
if ( ~index ) callbacks.splice( index, 1 );
const index = handlers.indexOf( handler );
if ( ~index ) handlers.splice( index, 1 );
}
};
};

View File

@ -57,7 +57,7 @@ export default function addComponentAttributes ( generator, node, local ) {
const usedContexts = new Set();
attribute.expression.arguments.forEach( arg => {
const contexts = generator.contextualise( arg, true );
const contexts = generator.contextualise( arg, true, true );
contexts.forEach( context => {
usedContexts.add( context );
@ -75,32 +75,13 @@ export default function addComponentAttributes ( generator, node, local ) {
return `var ${listName} = this.__svelte.${listName}, ${indexName} = this.__svelte.${indexName}, ${name} = ${listName}[${indexName}]`;
});
const handlerName = generator.current.counter( `${attribute.name}Handler` );
const handlerBody = ( declarations.length ? declarations.join( '\n' ) + '\n\n' : '' ) + `[✂${attribute.expression.start}-${attribute.expression.end}✂];`;
if ( attribute.name in generator.events ) {
local.init.push( deindent`
const ${handlerName} = template.events.${attribute.name}( ${local.name}, function ( event ) {
${local.name}.on( '${attribute.name}', function ( event ) {
${handlerBody}
});
` );
local.teardown.push( deindent`
${handlerName}.teardown();
` );
} else {
local.init.push( deindent`
function ${handlerName} ( event ) {
${handlerBody}
}
${local.name}.addEventListener( '${attribute.name}', ${handlerName}, false );
` );
local.teardown.push( deindent`
${local.name}.removeEventListener( '${attribute.name}', ${handlerName}, false );
` );
}
}
else if ( attribute.type === 'Binding' ) {

View File

@ -0,0 +1,3 @@
<button on:click='fire("select", { selection: "foo" })'>select foo</button>
<button on:click='fire("select", { selection: "bar" })'>select bar</button>
<button on:click='fire("select", { selection: "baz" })'>select baz</button>

View File

@ -0,0 +1,26 @@
import * as assert from 'assert';
export default {
test ( component, target, window ) {
const buttons = target.querySelectorAll( 'button' );
const click = new window.MouseEvent( 'click' );
const selected = [];
component.on( 'select', selection => {
selected.push( selection );
});
buttons[1].dispatchEvent( click );
buttons[2].dispatchEvent( click );
buttons[1].dispatchEvent( click );
buttons[0].dispatchEvent( click );
assert.deepEqual( selected, [
'bar',
'baz',
'bar',
'foo'
]);
}
};

View File

@ -0,0 +1,11 @@
<div>
<Widget on:select='fire("select", event.selection)'/>
</div>
<script>
import Widget from './Widget.html';
export default {
components: { Widget }
};
</script>

View File

@ -0,0 +1 @@
<p>i am a widget</p>

View File

@ -0,0 +1,23 @@
import * as assert from 'assert';
export default {
data: {
visible: true
},
html: '<div><!--#if visible--><p>i am a widget</p></div>', // TODO comment should follow component...
test ( component ) {
let count = 0;
component.on( 'widgetTornDown', function () {
assert.equal( this, component );
count += 1;
});
component.set({ visible: false });
assert.equal( count, 1 );
component.set({ visible: true });
component.set({ visible: false });
assert.equal( count, 2 );
}
};

View File

@ -0,0 +1,13 @@
<div>
{{#if visible}}
<Widget on:teardown='fire("widgetTornDown")'/>
{{/if}}
</div>
<script>
import Widget from './Widget.html';
export default {
components: { Widget }
};
</script>