Skip to content

Commit 7e6f893

Browse files
committedAug 1, 2018
fix: Support default export in functional component
1 parent 5f4c024 commit 7e6f893

File tree

2 files changed

+60
-23
lines changed

2 files changed

+60
-23
lines changed
 

‎packages/babel-sugar-functional-vue/src/index.js

+43-23
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,12 @@ const isInMethod = (t, path, parentLimitPath) => {
1818
}
1919

2020
/**
21-
* Check if it's a functional componet declarator
21+
* Check path has JSX
2222
* @param t
2323
* @param path
2424
* @returns boolean
2525
*/
26-
const isFunctionalComponentDeclarator = (t, path) => {
27-
const firstCharacter = path.get('id.name').node[0]
28-
if (firstCharacter < 'A' || firstCharacter > 'Z') {
29-
return false
30-
}
31-
26+
const hasJSX = (t, path) => {
3227
let hasJSX = false
3328

3429
path.traverse({
@@ -39,10 +34,41 @@ const isFunctionalComponentDeclarator = (t, path) => {
3934
},
4035
})
4136

42-
if (!hasJSX) {
37+
return hasJSX
38+
}
39+
40+
/**
41+
* Check if it's a functional componet declarator
42+
* @param t
43+
* @param path
44+
* @returns boolean
45+
*/
46+
const isFunctionalComponentDeclarator = (t, path) => {
47+
const firstCharacter = path.get('id.name').node[0]
48+
if (firstCharacter < 'A' || firstCharacter > 'Z') {
4349
return false
4450
}
45-
return true
51+
52+
return hasJSX(t, path)
53+
}
54+
55+
/**
56+
* Convert arrow function to functional component
57+
* @param t
58+
* @param path
59+
* @param name
60+
*/
61+
const convertFunctionalComponent = (t, path, name = null) => {
62+
const params = [t.identifier('h'), ...path.node.params]
63+
const body = path.node.body
64+
const props = [
65+
t.objectProperty(t.identifier('functional'), t.booleanLiteral(true)),
66+
t.objectProperty(t.identifier('render'), t.arrowFunctionExpression(params, body)),
67+
]
68+
if (process.env.NODE_ENV === 'development' && name) {
69+
props.unshift(t.objectProperty(t.identifier('name'), t.stringLiteral(name)))
70+
}
71+
path.replaceWith(t.objectExpression(props))
4672
}
4773

4874
export default babel => {
@@ -53,6 +79,13 @@ export default babel => {
5379
visitor: {
5480
Program(path) {
5581
path.traverse({
82+
ExportDefaultDeclaration(path) {
83+
if (!t.isArrowFunctionExpression(path.node.declaration) || !hasJSX(t, path)) {
84+
return
85+
}
86+
87+
convertFunctionalComponent(t, path.get('declaration'))
88+
},
5689
VariableDeclaration(path) {
5790
if (
5891
path.node.declarations.length !== 1 ||
@@ -69,20 +102,7 @@ export default babel => {
69102
}
70103

71104
const name = path.node.declarations[0].id.name
72-
const params = [t.identifier('h'), ...path.node.declarations[0].init.params]
73-
const body = path.node.declarations[0].init.body
74-
const isDevEnv = process.env.NODE_ENV === 'development'
75-
const props = [
76-
t.objectProperty(t.identifier('functional'), t.booleanLiteral(true)),
77-
t.objectProperty(t.identifier('render'), t.arrowFunctionExpression(params, body)),
78-
]
79-
if (isDevEnv) {
80-
props.unshift(t.objectProperty(t.identifier('name'), t.stringLiteral(name)))
81-
}
82-
path.replaceWith(
83-
t.variableDeclaration('const', [t.variableDeclarator(t.identifier(name), t.objectExpression(props))]),
84-
[],
85-
)
105+
convertFunctionalComponent(t, path.get('declarations')[0].get('init'), name)
86106
},
87107
})
88108
},

‎packages/babel-sugar-functional-vue/test/test.js

+17
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,23 @@ const tests = [
6565
6666
});`,
6767
},
68+
{
69+
name: 'Default export',
70+
from: `export default ({ props, listeners }) => <div onClick={listeners.click}>{props.msg}</div>`,
71+
to: `export default {
72+
functional: true,
73+
render: (h, {
74+
props,
75+
listeners
76+
}) => <div onClick={listeners.click}>{props.msg}</div>
77+
};`,
78+
},
79+
{
80+
name: 'Ignore non-arrow function',
81+
from: `const a = 2; export default 3`,
82+
to: `const a = 2;
83+
export default 3;`,
84+
},
6885
]
6986

7087
tests.map(({ name, from, to, NODE_ENV }) => {

0 commit comments

Comments
 (0)