Skip to content

Commit

Permalink
feat: simplify the template component's rendering function
Browse files Browse the repository at this point in the history
  • Loading branch information
meixg committed May 23, 2022
1 parent 093c65a commit 1955ddc
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 3 deletions.
84 changes: 83 additions & 1 deletion src/compilers/renderer-compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ export class RendererCompiler {
DEF('...info')
]
const fn = new FunctionDefinition(this.options.functionName || '', args,
this.compileComponentRendererBody(componentInfo)
componentInfo.componentType === 'template'
? this.compileTemplateComponentRendererBody(componentInfo)
: this.compileComponentRendererBody(componentInfo)
)
mergeLiteralAdd(fn)
return fn
Expand Down Expand Up @@ -132,6 +134,68 @@ export class RendererCompiler {
return body
}

private compileTemplateComponentRendererBody (info: ComponentInfo) {
const body = []
// 没有 ANode 的组件,比如 load-success 样例
if (!info.root) {
body.push(RETURN(L('')))
return body
}

// 兼容多参数的情况
body.push(new If(
new BinaryExpression(
BINARY(I('info'), '.', I('length')),
'===',
L(1)
),
[ASSIGN(I('info'), BINARY(
BINARY(I('info'), '[]', L(0)),
'||',
L({})
))]
))
body.push(new Else([
ASSIGN(I('info'), new MapLiteral([
[I('noDataOutput'), BINARY(I('info'), '[]', L(1))],
[I('parentCtx'), BINARY(I('info'), '[]', L(2))],
[I('slots'), BINARY(I('info'), '[]', L(4))]
]))
]))

// get params from info
body.push(createDefineWithDefaultValue('noDataOutput', BINARY(I('info'), '.', I('noDataOutput')), L(false)))
body.push(createDefineWithDefaultValue('parentCtx', BINARY(I('info'), '.', I('parentCtx')), NULL))
body.push(createDefineWithDefaultValue('slots', BINARY(I('info'), '.', I('slots')), EMPTY_MAP))

// helper
body.push(new ImportHelper('_'))

// instance preraration
if (info.hasMethod('initData')) {
if (this.options.useProvidedComponentClass) {
body.push(STATEMENT(new CreateComponentPrototype(info)))
}
// context
body.push(this.compileGenInstance(info))
body.push(...this.compileTemplateComponentContext())
body.push(...this.emitInitData())
} else {
body.push(DEF('instance', I('{}')))
body.push(...this.compileTemplateComponentContext())
}

body.push(DEF('html', L('')))
body.push(ASSIGN(I('parentCtx'), I('ctx')))
const aNodeCompiler = new ANodeCompiler(
info, !!this.options.ssrOnly, this.id, this.options.useProvidedComponentClass
)
body.push(...aNodeCompiler.compile(info.root, true))

body.push(RETURN(I('html')))
return body
}

private compileGenInstance (info: ComponentInfo) {
return DEF('instance', new CreateComponentInstance(info))
}
Expand Down Expand Up @@ -185,6 +249,24 @@ export class RendererCompiler {
]
}

private compileTemplateComponentContext () {
return [
ASSIGN(
BINARY(I('instance'), '.', I('sourceSlots')),
new FunctionCall(
BINARY(I('_'), '.', I('mergeChildSlots')),
[I('slots')]
)
),
DEF('ctx', new MapLiteral([
I('instance'),
I('slots'),
I('data'),
I('parentCtx')
]))
]
}

/**
* 产出 initData() 的函数调用
*
Expand Down
5 changes: 3 additions & 2 deletions src/models/component-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ export type ComponentType = 'normal' | 'template'
* 所有类型的 ComponentInfo,都需要实现如下接口
*/
export interface ComponentInfo {
id: string,
root: ANode,
id: string
root: ANode
childComponents: Map<TagName, ComponentReference>
componentType: ComponentType
hasMethod (name: string): boolean
getComputedNames (): string[]
getFilterNames (): string[]
Expand Down
54 changes: 54 additions & 0 deletions test/cases/provide-class-template-component/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const san = require('san')
const List = san.defineTemplateComponent({
initData () {
return {
text: 'child'
}
},
template: '<div>{{ text }}</div>'
})

const CompB = san.defineTemplateComponent({
initData () {
return {
text: 'comp b'
}
},
template: '<div>{{ text }}</div>'
})
const CompA = san.defineComponent({
components: {
'x-l': CompB
},
initData () {
return {
text: 'component a'
}
},
template: '<div><div>{{ text }}</div><x-l/></div>'
})

const MyComponent = san.defineComponent({
components: {
'x-l': List,
'x-g': san.createComponentLoader({
load: () => {
return List
},
placeholder: CompA
})
},
initData () {
return {
c: 'x-l'
}
},
trimWhitespace: 'all',
template: `<div>
<div s-is="c"></div>
<x-l/>
<x-g/>
</div>`
})

exports = module.exports = MyComponent
2 changes: 2 additions & 0 deletions test/cases/provide-class-template-component/data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{
}
1 change: 1 addition & 0 deletions test/cases/provide-class-template-component/expected.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div><!--s-data:{"c": "x-l"}--><div>child</div><div>child</div><div><div>component a</div><div>comp b</div></div></div>
12 changes: 12 additions & 0 deletions test/cases/provide-class-template-component/ssr-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { SsrSpecConfig } from '../../e2e.spec'

export default {
enabled: {
jssrc: false,
comsrc: true,
comrdr: false
},
compileOptions: {
useProvidedComponentClass: true
}
} as SsrSpecConfig

0 comments on commit 1955ddc

Please sign in to comment.