Skip to content
This repository has been archived by the owner on Aug 25, 2020. It is now read-only.

Commit

Permalink
feat: support fragment
Browse files Browse the repository at this point in the history
  • Loading branch information
HcySunYang committed Jul 3, 2020
1 parent 25fe6d8 commit a519000
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 1 deletion.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,17 @@ const App = {

In Vue3, the children of KeepAlive and Teleport components will not be built as `slots`, so you can use them as in the template:

## Fragment

Since Vue3 supports multiple root elements, so we need to support `Fragment`:

```html
<>
<p>foo</p>
<div>bar</div>
</>
```

## Optimization mode

`Vue3` makes full use of compile-time information to generate `PatchFlags` for runtime update performance improvement, `vue-next-jsx` behaves as `Vue3 Compiler` after enabling **optimization mode**.
Expand Down
5 changes: 4 additions & 1 deletion src/buildCreateVNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,10 @@ function processJSXAttrValue(value: bt.JSXAttribute['value']) {
}
}

function buildChildren(children: bt.JSXElement['children'], state: State) {
export function buildChildren(
children: bt.JSXElement['children'],
state: State
) {
return bt.arrayExpression(
children
.map((child) => {
Expand Down
17 changes: 17 additions & 0 deletions src/buildFragment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as bt from '@babel/types'
import { NodePath } from '@babel/traverse'
import { State } from './main'
import { buildChildren } from './buildCreateVNode'

export function buildFragment(
jsxElementPath: NodePath<bt.JSXFragment>,
state: State
) {
const createVNode = state.visitorContext.addHelper('createVNode')
const Fragment = state.visitorContext.addHelper('Fragment')
return bt.callExpression(createVNode, [
Fragment,
bt.nullLiteral(),
buildChildren(jsxElementPath.node.children, state)
])
}
7 changes: 7 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import jsx from '@babel/plugin-syntax-jsx'
import * as bt from '@babel/types'
import { Visitor, NodePath } from '@babel/traverse'
import { buildCreateVNodeCall } from './buildCreateVNode'
import { buildFragment } from './buildFragment'

export interface Options {
optimizate?: boolean
Expand Down Expand Up @@ -94,6 +95,12 @@ export default function VueNextJSX() {
state.opts = { ...defaultOptions, ...state.opts }
path.replaceWith(buildCreateVNodeCall(path, state))
}
},
JSXFragment: {
exit(path: NodePath<bt.JSXFragment>, state: State) {
state.opts = { ...defaultOptions, ...state.opts }
path.replaceWith(buildFragment(path, state))
}
}
} as Visitor
}
Expand Down
6 changes: 6 additions & 0 deletions tests/__snapshots__/fragment.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Fragment <> 1`] = `
"import { createVNode, Fragment } from \\"vue\\";
const el = createVNode(Fragment, null, [createVNode(\\"p\\")]);"
`;
14 changes: 14 additions & 0 deletions tests/fragment.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { transformWithPlugin } from './utils'

describe('Fragment', () => {
test('<>', () => {
const code = `
const el = (
<>
<p></p>
</>
)
`
transformWithPlugin(code)
})
})

0 comments on commit a519000

Please sign in to comment.