diff --git a/src/generators/dom/visitors/IfBlock.js b/src/generators/dom/visitors/IfBlock.js index be96352edf..1f1800b536 100644 --- a/src/generators/dom/visitors/IfBlock.js +++ b/src/generators/dom/visitors/IfBlock.js @@ -44,16 +44,73 @@ function visitChildren ( generator, block, state, node ) { } export default function visitIfBlock ( generator, block, state, node ) { - const params = block.params.join( ', ' ); const name = generator.getUniqueName( `if_block` ); - const getBlock = block.getUniqueName( `get_block` ); - const current_block = block.getUniqueName( `current_block` ); + const anchor = generator.getUniqueName( `${name}_anchor` ); + const params = block.params.join( ', ' ); + + const vars = { name, anchor, params }; + + block.createAnchor( anchor, state.parentNode ); const branches = getBranches( generator, block, state, node, generator.getUniqueName( `create_if_block` ) ); const dynamic = branches.some( branch => branch.dynamic ); - const anchor = `${name}_anchor`; - block.createAnchor( anchor, state.parentNode ); + if ( node.else ) { + compound( generator, block, state, node, branches, dynamic, vars ); + } else { + simple( generator, block, state, node, branches[0], dynamic, vars ); + } + + block.builders.destroy.addLine( + `if ( ${name} ) ${name}.destroy( ${state.parentNode ? 'false' : 'detach'} );` + ); +} + +function simple ( generator, block, state, node, branch, dynamic, { name, anchor, params } ) { + block.builders.create.addBlock( deindent` + var ${name} = ${branch.condition} && ${branch.block}( ${params}, ${block.component} ); + ` ); + + const isToplevel = !state.parentNode; + + if ( isToplevel ) { + block.builders.mount.addLine( `if ( ${name} ) ${name}.mount( ${block.target}, ${anchor} );` ); + } else { + block.builders.create.addLine( `if ( ${name} ) ${name}.mount( ${state.parentNode}, ${anchor} );` ); + } + + if ( dynamic ) { + block.builders.update.addBlock( deindent` + if ( ${branch.condition} ) { + if ( ${name} ) { + ${name}.update( changed, ${params} ); + } else { + ${name} = ${branch.block}( ${params}, ${block.component} ); + ${name}.mount( ${anchor}.parentNode, ${anchor} ); + } + } else if ( ${name} ) { + ${name}.destroy( true ); + ${name} = null; + } + ` ); + } else { + block.builders.update.addBlock( deindent` + if ( ${branch.condition} ) { + if ( !${name} ) { + ${name} = ${branch.block}( ${params}, ${block.component} ); + ${name}.mount( ${anchor}.parentNode, ${anchor} ); + } + } else if ( ${name} ) { + ${name}.destroy( true ); + ${name} = null; + } + ` ); + } +} + +function compound ( generator, block, state, node, branches, dynamic, { name, anchor, params } ) { + const getBlock = block.getUniqueName( `get_block` ); + const current_block = block.getUniqueName( `current_block` ); block.builders.create.addBlock( deindent` function ${getBlock} ( ${params} ) { @@ -93,8 +150,4 @@ export default function visitIfBlock ( generator, block, state, node ) { } ` ); } - - block.builders.destroy.addLine( - `if ( ${name} ) ${name}.destroy( ${isToplevel ? 'detach' : 'false'} );` - ); } \ No newline at end of file diff --git a/test/js/samples/if-block-simple/expected.js b/test/js/samples/if-block-simple/expected.js new file mode 100644 index 0000000000..f1ca09dc3a --- /dev/null +++ b/test/js/samples/if-block-simple/expected.js @@ -0,0 +1,93 @@ +import { appendNode, assign, createComment, createElement, createText, detachNode, dispatchObservers, insertNode, proto } from "svelte/shared.js"; + +function create_main_fragment ( root, component ) { + var if_block_anchor = createComment(); + + var if_block = root.foo && create_if_block( root, component ); + + return { + mount: function ( target, anchor ) { + insertNode( if_block_anchor, target, anchor ); + if ( if_block ) if_block.mount( target, if_block_anchor ); + }, + + update: function ( changed, root ) { + if ( root.foo ) { + if ( !if_block ) { + if_block = create_if_block( root, component ); + if_block.mount( if_block_anchor.parentNode, if_block_anchor ); + } + } else if ( if_block ) { + if_block.destroy( true ); + if_block = null; + } + }, + + destroy: function ( detach ) { + if ( if_block ) if_block.destroy( detach ); + + if ( detach ) { + detachNode( if_block_anchor ); + } + } + }; +} + +function create_if_block ( root, component ) { + var p = createElement( 'p' ); + appendNode( createText( "foo!" ), p ); + + return { + mount: function ( target, anchor ) { + insertNode( p, target, anchor ); + }, + + destroy: function ( detach ) { + if ( detach ) { + detachNode( p ); + } + } + }; +} + +function SvelteComponent ( options ) { + options = options || {}; + this._state = options.data || {}; + + this._observers = { + pre: Object.create( null ), + post: Object.create( null ) + }; + + this._handlers = Object.create( null ); + + this._root = options._root; + this._yield = options._yield; + + this._torndown = false; + + this._fragment = create_main_fragment( this._state, this ); + if ( options.target ) this._fragment.mount( options.target, null ); +} + +assign( SvelteComponent.prototype, proto ); + +SvelteComponent.prototype._set = function _set ( newState ) { + var oldState = this._state; + this._state = assign( {}, oldState, newState ); + dispatchObservers( this, this._observers.pre, newState, oldState ); + if ( this._fragment ) this._fragment.update( newState, this._state ); + dispatchObservers( this, this._observers.post, newState, oldState ); +}; + +SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) { + this.fire( 'destroy' ); + + this._fragment.destroy( detach !== false ); + this._fragment = null; + + this._state = {}; + this._torndown = true; +}; + +export default SvelteComponent; \ No newline at end of file diff --git a/test/js/samples/if-block-simple/input.html b/test/js/samples/if-block-simple/input.html new file mode 100644 index 0000000000..050095b913 --- /dev/null +++ b/test/js/samples/if-block-simple/input.html @@ -0,0 +1,3 @@ +{{#if foo}} +

foo!

+{{/if}} \ No newline at end of file