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

Merge pull request #107 from sveltejs/Swatinem-separatemount

#91 again
This commit is contained in:
Rich Harris 2016-12-04 10:14:09 -05:00 committed by GitHub
commit 5770048855
6 changed files with 101 additions and 28 deletions

View File

@ -34,12 +34,12 @@ export default function generate ( parsed, source, options ) {
},
createMountStatement ( name ) {
if ( generator.current.useAnchor && generator.current.target === 'target' ) {
generator.current.initStatements.push( deindent `
anchor.parentNode.insertBefore( ${name}, anchor );
if ( generator.current.target === 'target' ) {
generator.current.mountStatements.push( deindent`
target.insertBefore( ${name}, anchor );
` );
} else {
generator.current.initStatements.push( deindent `
generator.current.initStatements.push( deindent`
${generator.current.target}.appendChild( ${name} );
` );
}
@ -58,10 +58,14 @@ export default function generate ( parsed, source, options ) {
}
renderers.push( deindent`
function ${fragment.name} ( ${fragment.params}, component, target${fragment.useAnchor ? ', anchor' : ''} ) {
function ${fragment.name} ( ${fragment.params}, component ) {
${fragment.initStatements.join( '\n\n' )}
return {
mount: function ( target, anchor ) {
${fragment.mountStatements.join( '\n\n' )}
},
update: function ( changed, ${fragment.params} ) {
${fragment.updateStatements.join( '\n\n' )}
},
@ -249,6 +253,7 @@ export default function generate ( parsed, source, options ) {
localElementDepth: 0,
initStatements: [],
mountStatements: [],
updateStatements: [],
teardownStatements: [],
@ -377,13 +382,17 @@ export default function generate ( parsed, source, options ) {
if ( generator.hasComplexBindings ) {
initStatements.push( deindent`
this.__bindings = [];
var mainFragment = renderMainFragment( state, this, options.target );
var mainFragment = renderMainFragment( state, this );
if ( options.target ) this.mount( options.target );
while ( this.__bindings.length ) this.__bindings.pop()();
` );
setStatements.push( `while ( this.__bindings.length ) this.__bindings.pop()();` );
} else {
initStatements.push( `var mainFragment = renderMainFragment( state, this, options.target );` );
initStatements.push( deindent`
var mainFragment = renderMainFragment( state, this );
if ( options.target ) this.mount( options.target );
` );
}
if ( generator.hasComponents ) {
@ -462,6 +471,10 @@ export default function generate ( parsed, source, options ) {
${setStatements.join( '\n\n' )}
};
this.mount = function mount ( target, anchor ) {
mainFragment.mount( target, anchor );
}
this.observe = function ( key, callback, options ) {
var group = ( options && options.defer ) ? observers.deferred : observers.immediate;

View File

@ -5,10 +5,13 @@ export default {
enter ( generator, node ) {
const i = generator.counters.each++;
const name = `eachBlock_${i}`;
const iterations = `${name}_iterations`;
const renderer = `renderEachBlock_${i}`;
const listName = `${name}_value`;
const isToplevel = generator.current.localElementDepth === 0;
generator.addSourcemapLocations( node.expression );
const { dependencies, snippet } = generator.contextualise( node.expression );
@ -17,39 +20,44 @@ export default {
generator.current.initStatements.push( deindent`
var ${name}_value = ${snippet};
var ${name}_fragment = document.createDocumentFragment();
var ${name}_iterations = [];
var ${iterations} = [];
for ( var i = 0; i < ${name}_value.length; i += 1 ) {
${name}_iterations[i] = ${renderer}( ${generator.current.params}, ${listName}, ${listName}[i], i, component, ${name}_fragment );
${iterations}[i] = ${renderer}( ${generator.current.params}, ${listName}, ${listName}[i], i, component );
${!isToplevel ? `${iterations}[i].mount( ${anchor}.parentNode, ${anchor} );` : ''}
}
${anchor}.parentNode.insertBefore( ${name}_fragment, ${anchor} );
` );
if ( isToplevel ) {
generator.current.mountStatements.push( deindent`
for ( var i = 0; i < ${iterations}.length; i += 1 ) {
${iterations}[i].mount( ${anchor}.parentNode, ${anchor} );
}
` );
}
generator.current.updateStatements.push( deindent`
var ${name}_value = ${snippet};
for ( var i = 0; i < ${name}_value.length; i += 1 ) {
if ( !${name}_iterations[i] ) {
${name}_iterations[i] = ${renderer}( ${generator.current.params}, ${listName}, ${listName}[i], i, component, ${name}_fragment );
if ( !${iterations}[i] ) {
${iterations}[i] = ${renderer}( ${generator.current.params}, ${listName}, ${listName}[i], i, component );
${iterations}[i].mount( ${anchor}.parentNode, ${anchor} );
} else {
${name}_iterations[i].update( changed, ${generator.current.params}, ${listName}, ${listName}[i], i );
${iterations}[i].update( changed, ${generator.current.params}, ${listName}, ${listName}[i], i );
}
}
for ( var i = ${name}_value.length; i < ${name}_iterations.length; i += 1 ) {
${name}_iterations[i].teardown( true );
for ( var i = ${name}_value.length; i < ${iterations}.length; i += 1 ) {
${iterations}[i].teardown( true );
}
${anchor}.parentNode.insertBefore( ${name}_fragment, ${anchor} );
${name}_iterations.length = ${listName}.length;
${iterations}.length = ${listName}.length;
` );
const isToplevel = generator.current.localElementDepth === 0;
generator.current.teardownStatements.push( deindent`
for ( var i = 0; i < ${name}_iterations.length; i += 1 ) {
${name}_iterations[i].teardown( ${isToplevel ? 'detach' : 'false'} );
for ( var i = 0; i < ${iterations}.length; i += 1 ) {
${iterations}[i].teardown( ${isToplevel ? 'detach' : 'false'} );
}
` );
@ -87,6 +95,7 @@ export default {
params,
initStatements: [],
mountStatements: [],
updateStatements: [ Object.keys( contexts ).map( contextName => {
const listName = listNames[ contextName ];
const indexName = indexNames[ contextName ];

View File

@ -15,6 +15,7 @@ export default {
allUsedContexts: new Set(),
init: [],
mount: [],
update: [],
teardown: []
};
@ -57,7 +58,7 @@ export default {
${statements.join( '\n\n' )}
var ${name} = new template.components.${node.name}({
target: ${generator.current.target},
target: ${!isToplevel ? generator.current.target: 'null'},
root: component.root || component,
data: ${name}_initialData
});
@ -65,12 +66,16 @@ export default {
} else {
local.init.unshift( deindent`
var ${name} = new template.components.${node.name}({
target: ${generator.current.target},
target: ${!isToplevel ? generator.current.target: 'null'},
root: component.root || component
});
` );
}
if ( isToplevel ) {
local.mount.unshift( `${name}.mount( target, anchor );` );
}
if ( local.dynamicAttributes.length ) {
const updates = local.dynamicAttributes.map( attribute => {
return deindent`
@ -146,6 +151,7 @@ export default {
generator.current.initStatements.push( local.init.join( '\n' ) );
if ( local.update.length ) generator.current.updateStatements.push( local.update.join( '\n' ) );
if ( local.mount.length ) generator.current.mountStatements.push( local.mount.join( '\n' ) );
generator.current.teardownStatements.push( local.teardown.join( '\n' ) );
generator.push({

View File

@ -11,6 +11,7 @@ function generateBlock ( generator, node, name ) {
localElementDepth: 0,
initStatements: [],
mountStatements: [],
updateStatements: [],
teardownStatements: [],
@ -54,11 +55,12 @@ export default {
enter ( generator, node ) {
const i = generator.counters.if++;
const { params, target } = generator.current;
const { params } = generator.current;
const name = `ifBlock_${i}`;
const getBlock = `getBlock_${i}`;
const currentBlock = `currentBlock_${i}`;
const isToplevel = generator.current.localElementDepth === 0;
const conditionsAndBlocks = getConditionsAndBlocks( generator, node, `renderIfBlock_${i}` );
const anchor = generator.createAnchor( name, `#if ${generator.source.slice( node.expression.start, node.expression.end )}` );
@ -71,9 +73,16 @@ export default {
}
var ${currentBlock} = ${getBlock}( ${params} );
var ${name} = ${currentBlock} && ${currentBlock}( ${params}, component, ${target}, ${anchor} );
var ${name} = ${currentBlock} && ${currentBlock}( ${params}, component );
` );
const mountStatement = `if ( ${name} ) ${name}.mount( ${anchor}.parentNode, ${anchor} );`;
if ( isToplevel ) {
generator.current.mountStatements.push( mountStatement );
} else {
generator.current.initStatements.push( mountStatement );
}
generator.current.updateStatements.push( deindent`
var _${currentBlock} = ${currentBlock};
${currentBlock} = ${getBlock}( ${params} );
@ -81,11 +90,11 @@ export default {
${name}.update( changed, ${params} );
} else {
if ( ${name} ) ${name}.teardown( true );
${name} = ${currentBlock} && ${currentBlock}( ${params}, component, ${target}, ${anchor} );
${name} = ${currentBlock} && ${currentBlock}( ${params}, component );
if ( ${name} ) ${name}.mount( ${anchor}.parentNode, ${anchor} );
}
` );
const isToplevel = generator.current.localElementDepth === 0;
generator.current.teardownStatements.push( deindent`
if ( ${name} ) ${name}.teardown( ${isToplevel ? 'detach' : 'false'} );
` );

View File

@ -0,0 +1,33 @@
const VALUES = Array.from( 'abcdefghijklmnopqrstuvwxyz' );
function permute () {
const values = VALUES.slice();
const number = Math.floor(Math.random() * VALUES.length);
const permuted = [];
for (let i = 0; i < number; i++) {
permuted.push( ...values.splice( Math.floor( Math.random() * ( number - i ) ), 1 ) );
}
return {
data: permuted,
expected: permuted.length ? `(${permuted.join(')(')})` : ''
};
}
let step = permute();
export default {
data: {
values: step.data
},
html: step.expected,
test ( assert, component, target ) {
for (let i = 0; i < 100; i++) {
step = permute();
component.set({ values: step.data });
assert.htmlEqual( target.innerHTML, step.expected );
}
}
};

View File

@ -0,0 +1,3 @@
{{#each values as value}}
({{value}})
{{/each}}