support dynamic simple if-blocks

pull/7738/head
Rich-Harris 9 years ago
parent 0a62ac7619
commit a839f7fc9a

@ -63,14 +63,13 @@ export default function visitElement ( generator, block, state, node ) {
}); });
if ( intro || outro ) addTransitions( generator, block, childState, node, intro, outro ); if ( intro || outro ) addTransitions( generator, block, childState, node, intro, outro );
}
if ( !outro && !state.parentNode ) { if ( !state.parentNode ) {
// TODO this probably doesn't belong here. We eventually need to consider // TODO we eventually need to consider what happens to elements
// what happens to elements that belong to the same outgroup as an // that belong to the same outgroup as an outroing element...
// outroing element...
block.builders.detach.addLine( `${generator.helper( 'detachNode' )}( ${name} );` ); block.builders.detach.addLine( `${generator.helper( 'detachNode' )}( ${name} );` );
} }
}
if ( node.name !== 'select' ) { if ( node.name !== 'select' ) {
// <select> value attributes are an annoying special case — it must be handled // <select> value attributes are an annoying special case — it must be handled

@ -22,7 +22,6 @@ export default function addTransitions ( generator, block, state, node, intro, o
block.builders.outro.addBlock( deindent` block.builders.outro.addBlock( deindent`
${name}.run( ${name}.t, 0, function () { ${name}.run( ${name}.t, 0, function () {
${generator.helper( 'detachNode' )}( ${state.name} );
${block.component}.fire( 'outro.end', { node: ${state.name} }); ${block.component}.fire( 'outro.end', { node: ${state.name} });
if ( --${block.alias( 'outros' )} === 0 ) ${block.alias( 'outrocallback' )}(); if ( --${block.alias( 'outros' )} === 0 ) ${block.alias( 'outrocallback' )}();
${name} = null; ${name} = null;
@ -60,10 +59,11 @@ export default function addTransitions ( generator, block, state, node, intro, o
const fn = `${generator.alias( 'template' )}.transitions.${outro.name}`; const fn = `${generator.alias( 'template' )}.transitions.${outro.name}`;
// TODO hide elements that have outro'd (unless they belong to a still-outroing
// group) prior to their removal from the DOM
block.builders.outro.addBlock( deindent` block.builders.outro.addBlock( deindent`
${outroName} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, false, null ); ${outroName} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, false, null );
${outroName}.run( 1, 0, function () { ${outroName}.run( 1, 0, function () {
${generator.helper( 'detachNode' )}( ${state.name} );
${block.component}.fire( 'outro.end', { node: ${state.name} }); ${block.component}.fire( 'outro.end', { node: ${state.name} });
if ( --${block.alias( 'outros' )} === 0 ) ${block.alias( 'outrocallback' )}(); if ( --${block.alias( 'outros' )} === 0 ) ${block.alias( 'outrocallback' )}();
}); });

@ -86,37 +86,26 @@ function simple ( generator, block, state, node, branch, dynamic, { name, anchor
const parentNode = state.parentNode || `${anchor}.parentNode`; const parentNode = state.parentNode || `${anchor}.parentNode`;
const exit = branch.hasOutroTransitions ? const enter = dynamic ?
deindent` ( branch.hasIntroTransitions ?
${name}.outro( function () {
${name}.destroy( true );
${name} = null;
});
` :
deindent` deindent`
${name}.destroy( true ); if ( ${name} ) {
${name} = null; ${name}.update( changed, ${params} );
`; } else {
${name} = ${branch.block}( ${params}, ${block.component} );
if ( dynamic ) {
if ( branch.hasIntroTransitions ) {
throw new Error( 'TODO simple dynamic if-block with intro transitions' );
} }
block.builders.update.addBlock( deindent` ${name}.intro( ${parentNode}, ${anchor} );
if ( ${branch.condition} ) { ` :
deindent`
if ( ${name} ) { if ( ${name} ) {
${name}.update( changed, ${params} ); ${name}.update( changed, ${params} );
} else { } else {
${name} = ${branch.block}( ${params}, ${block.component} ); ${name} = ${branch.block}( ${params}, ${block.component} );
${name}.mount( ${parentNode}, ${anchor} ); ${name}.mount( ${parentNode}, ${anchor} );
} }
} else if ( ${name} ) { ` ) :
${exit} ( branch.hasIntroTransitions ?
}
` );
} else {
const enter = branch.hasIntroTransitions ?
deindent` deindent`
if ( !${name} ) ${name} = ${branch.block}( ${params}, ${block.component} ); if ( !${name} ) ${name} = ${branch.block}( ${params}, ${block.component} );
${name}.intro( ${parentNode}, ${anchor} ); ${name}.intro( ${parentNode}, ${anchor} );
@ -126,6 +115,20 @@ function simple ( generator, block, state, node, branch, dynamic, { name, anchor
${name} = ${branch.block}( ${params}, ${block.component} ); ${name} = ${branch.block}( ${params}, ${block.component} );
${name}.mount( ${parentNode}, ${anchor} ); ${name}.mount( ${parentNode}, ${anchor} );
} }
` );
// no `update()` here — we don't want to update outroing nodes,
// as that will typically result in glitching
const exit = branch.hasOutroTransitions ?
deindent`
${name}.outro( function () {
${name}.destroy( true );
${name} = null;
});
` :
deindent`
${name}.destroy( true );
${name} = null;
`; `;
block.builders.update.addBlock( deindent` block.builders.update.addBlock( deindent`
@ -135,7 +138,6 @@ function simple ( generator, block, state, node, branch, dynamic, { name, anchor
${exit} ${exit}
} }
` ); ` );
}
} }
function compound ( generator, block, state, node, branches, dynamic, { name, anchor, params } ) { function compound ( generator, block, state, node, branches, dynamic, { name, anchor, params } ) {

@ -0,0 +1,47 @@
export default {
data: {
name: 'world'
},
test ( assert, component, target, window ) {
global.count = 0;
let now = 0;
let callback;
window.performance = { now: () => now };
global.requestAnimationFrame = cb => callback = cb;
component.set({ visible: true });
assert.equal( global.count, 1 );
const div = target.querySelector( 'div' );
assert.equal( div.foo, 0 );
now = 300;
callback();
component.set({ name: 'everybody' });
assert.equal( div.foo, 0.75 );
assert.htmlEqual( div.innerHTML, 'hello everybody!' );
component.set({ visible: false, name: 'again' });
assert.htmlEqual( div.innerHTML, 'hello everybody!' );
now = 500;
callback();
assert.equal( div.foo, 0.25 );
component.set({ visible: true });
now = 700;
callback();
assert.equal( div.foo, 0.75 );
assert.htmlEqual( div.innerHTML, 'hello again!' );
now = 800;
callback();
assert.equal( div.foo, 1 );
now = 900;
callback();
component.destroy();
}
};

@ -0,0 +1,19 @@
{{#if visible}}
<div transition:foo>hello {{name}}!</div>
{{/if}}
<script>
export default {
transitions: {
foo: function ( node, params ) {
global.count += 1;
return {
duration: 400,
tick: t => {
node.foo = t;
}
};
}
}
};
</script>
Loading…
Cancel
Save