Initial implementation of {{yield}}-generator

pull/112/head
Fabrice Weinberg 8 years ago
parent 49629c5403
commit 6c473a3466

@ -516,6 +516,7 @@ export default function generate ( parsed, source, options ) {
}; };
this.root = options.root; this.root = options.root;
this.yield = options.yield;
${initStatements.join( '\n\n' )} ${initStatements.join( '\n\n' )}
} }

@ -1,9 +1,11 @@
import deindent from '../utils/deindent.js'; import deindent from '../utils/deindent.js';
import addComponentAttributes from './attributes/addComponentAttributes.js'; import addComponentAttributes from './attributes/addComponentAttributes.js';
import addElementAttributes from './attributes/addElementAttributes.js'; import addElementAttributes from './attributes/addElementAttributes.js';
import counter from '../utils/counter.js';
export default { export default {
enter ( generator, node ) { enter ( generator, node ) {
const hasChildren = node.children.length > 0
const isComponent = node.name in generator.components; const isComponent = node.name in generator.components;
const name = generator.current.counter( isComponent ? `${node.name[0].toLowerCase()}${node.name.slice( 1 )}` : node.name ); const name = generator.current.counter( isComponent ? `${node.name[0].toLowerCase()}${node.name.slice( 1 )}` : node.name );
@ -27,13 +29,49 @@ export default {
addComponentAttributes( generator, node, local ); addComponentAttributes( generator, node, local );
const componentInitProperties = [
`target: ${!isToplevel ? generator.current.target: 'null'}`,
'root: component.root || component'
];
// Component has children
if ( hasChildren ) {
const yieldName = `render${name}YieldFragment`;
// {{YIELD STUFF}}
generator.push({
useAnchor: true,
name: generator.current.counter(yieldName),
target: 'target',
localElementDepth: 0,
initStatements: [],
mountStatements: [],
updateStatements: [],
teardownStatements: [],
counter: counter()
});
node.children.forEach( generator.visit );
generator.addRenderer( generator.current );
generator.pop();
// Don't render children twice
node.children = [];
generator.current.initStatements.push(`var ${name}_yieldFragment = ${yieldName}( root, component );`);
generator.current.updateStatements.push(`${name}_yieldFragment.update ( changed, root );`)
componentInitProperties.push(`yield: ${name}_yieldFragment`);
}
const statements = [];
if ( local.staticAttributes.length || local.dynamicAttributes.length || local.bindings.length ) { if ( local.staticAttributes.length || local.dynamicAttributes.length || local.bindings.length ) {
const initialProps = local.staticAttributes const initialProps = local.staticAttributes
.concat( local.dynamicAttributes ) .concat( local.dynamicAttributes )
.map( attribute => `${attribute.name}: ${attribute.value}` ); .map( attribute => `${attribute.name}: ${attribute.value}` );
const statements = [];
if ( initialProps.length ) { if ( initialProps.length ) {
statements.push( deindent` statements.push( deindent`
var ${name}_initialData = { var ${name}_initialData = {
@ -53,24 +91,17 @@ export default {
statements.push( bindings.join( '\n' ) ); statements.push( bindings.join( '\n' ) );
} }
componentInitProperties.push(`data: ${name}_initialData`);
}
local.init.unshift( deindent` local.init.unshift( deindent`
${statements.join( '\n\n' )} ${statements.join( '\n\n' )}
var ${name} = new template.components.${node.name}({
${componentInitProperties.join(',\n')}
});
` );
var ${name} = new template.components.${node.name}({
target: ${!isToplevel ? generator.current.target: 'null'},
root: component.root || component,
data: ${name}_initialData
});
` );
} else {
local.init.unshift( deindent`
var ${name} = new template.components.${node.name}({
target: ${!isToplevel ? generator.current.target: 'null'},
root: component.root || component
});
` );
}
if ( isToplevel ) { if ( isToplevel ) {
local.mount.unshift( `${name}.mount( target, anchor );` ); local.mount.unshift( `${name}.mount( target, anchor );` );

@ -0,0 +1,9 @@
import deindent from '../utils/deindent.js';
export default {
enter ( generator, node ) {
const anchor = generator.createAnchor( 'yield', 'yield' );
generator.current.mountStatements.push(`component.yield && component.yield.mount( ${generator.current.target}, ${anchor} );`);
generator.current.teardownStatements.push(`component.yield && component.yield.teardown( detach );`);
}
};

@ -4,6 +4,7 @@ import Element from './Element.js';
import IfBlock from './IfBlock.js'; import IfBlock from './IfBlock.js';
import MustacheTag from './MustacheTag.js'; import MustacheTag from './MustacheTag.js';
import Text from './Text.js'; import Text from './Text.js';
import YieldTag from './YieldTag.js';
export default { export default {
Comment, Comment,
@ -11,5 +12,6 @@ export default {
Element, Element,
IfBlock, IfBlock,
MustacheTag, MustacheTag,
Text Text,
YieldTag
}; };

@ -0,0 +1,15 @@
<p>
{{#if show}}
{{yield}}
{{/if}}
</p>
<script>
export default {
data(){
return {
show: false
}
}
}
</script>

@ -0,0 +1,13 @@
export default {
html: '<div><p></p></div>',
test ( assert, component, target ) {
const widget = component.refs.widget;
assert.equal( widget.get( 'show' ), false );
widget.set({show: true});
assert.equal( target.innerHTML, '<div><p>Hello<!--yield--><!--#if show--></p></div>' );
component.set({data: 'World'});
assert.equal( target.innerHTML, '<div><p>World<!--yield--><!--#if show--></p></div>' );
widget.set({show: false});
assert.equal( target.innerHTML, '<div><p><!--#if show--></p></div>' );
}
}

@ -0,0 +1,14 @@
<div>
<Widget ref:widget>{{data}}</Widget>
</div>
<script>
import Widget from './Widget.html'
export default {
components: { Widget },
data(){
return {
data: "Hello"
}
}
}
</script>

@ -0,0 +1,9 @@
export default {
html: '<div><p>Hello</p></div>',
test ( assert, component, target ) {
assert.equal( component.get( 'data' ), 'Hello' );
component.set({data: 'World'})
assert.equal( component.get( 'data' ), 'World' );
assert.equal( target.innerHTML, '<div><p>World<!--yield--></p></div>' );
}
}

@ -0,0 +1,14 @@
<div>
<Widget>{{data}}</Widget>
</div>
<script>
import Widget from './Widget.html'
export default {
components: { Widget },
data(){
return {
data: "Hello"
}
}
}
</script>

@ -0,0 +1,3 @@
export default {
html: '<p>Hello</p>'
}

@ -0,0 +1,15 @@
<p>
Hello
{{#if test}}
{{yield}}
{{/if}}
</p>
<script>
export default {
data(){
return {
test: true
}
}
}
</script>
Loading…
Cancel
Save