mirror of
https://github.com/sveltejs/svelte.git
synced 2024-12-01 17:30:59 +01:00
component events
This commit is contained in:
parent
abd8b77106
commit
24e768e4d2
@ -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 );
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -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' ) {
|
||||
|
3
test/compiler/component-events-data/Widget.html
Normal file
3
test/compiler/component-events-data/Widget.html
Normal 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>
|
26
test/compiler/component-events-data/_config.js
Normal file
26
test/compiler/component-events-data/_config.js
Normal 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'
|
||||
]);
|
||||
}
|
||||
};
|
11
test/compiler/component-events-data/main.html
Normal file
11
test/compiler/component-events-data/main.html
Normal 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>
|
1
test/compiler/component-events/Widget.html
Normal file
1
test/compiler/component-events/Widget.html
Normal file
@ -0,0 +1 @@
|
||||
<p>i am a widget</p>
|
23
test/compiler/component-events/_config.js
Normal file
23
test/compiler/component-events/_config.js
Normal 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 );
|
||||
}
|
||||
};
|
13
test/compiler/component-events/main.html
Normal file
13
test/compiler/component-events/main.html
Normal 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>
|
Loading…
Reference in New Issue
Block a user