diff --git a/packages/uni-migration/__tests__/wxml.spec.js b/packages/uni-migration/__tests__/wxml.spec.js
index aad6f6191d5cfa4bf50790494dc90300262e8e55..c49d5fe9f0ba0648f97d5e145108a88091c69eeb 100644
--- a/packages/uni-migration/__tests__/wxml.spec.js
+++ b/packages/uni-migration/__tests__/wxml.spec.js
@@ -10,17 +10,22 @@ describe('wxml:compiler', () => {
assertCodegen(
``,
``
- )
- assertCodegen(
- ``,
- ``
- )
- })
- it('generate class', () => {
- assertCodegen(
- ``,
- ``
- )
+ )
+ assertCodegen(
+ ``,
+ ``
+ )
+ assertCodegen(
+ '',
+ // ``
+ ``
+ )
+ })
+ it('generate class', () => {
+ assertCodegen(
+ ``,
+ ``
+ )
})
it('generate v-if', () => {
assertCodegen(
@@ -40,10 +45,10 @@ describe('wxml:compiler', () => {
assertCodegen(
'',
``
- )
- assertCodegen(
- '',
- ``
+ )
+ assertCodegen(
+ '',
+ ``
)
})
it('generate root element', () => {
@@ -63,5 +68,27 @@ describe('wxml:compiler', () => {
'',
``
)
+
+ assertCodegen(
+ `
+`,
+ ``
+ )
+
+ assertCodegen(
+ '',
+ ``
+ )
+
+ assertCodegen(
+ '',
+ // ``
+ ``
+ )
+
+ assertCodegen(
+ '',
+ ``
+ )
})
-})
+})
diff --git a/packages/uni-migration/lib/mp-weixin/transform/file-transformer.js b/packages/uni-migration/lib/mp-weixin/transform/file-transformer.js
index 45dd0df5e4343b175ece34af4796ff26b1d22e17..3e29527616fd8e2fc8240c024852abc1c3c52fa2 100644
--- a/packages/uni-migration/lib/mp-weixin/transform/file-transformer.js
+++ b/packages/uni-migration/lib/mp-weixin/transform/file-transformer.js
@@ -50,7 +50,7 @@ module.exports = function transformFile(input, options) {
const commentsCode = options.silent ? '' :
`
-
+
`
return [
`${commentsCode}
@@ -66,4 +66,4 @@ ${styleCode}
deps,
wxsFiles
]
-}
+}
diff --git a/packages/uni-migration/lib/mp-weixin/transform/import-template.js b/packages/uni-migration/lib/mp-weixin/transform/import-template.js
new file mode 100644
index 0000000000000000000000000000000000000000..ed81df5672a409a01e54954175b7d24485fe6e9e
--- /dev/null
+++ b/packages/uni-migration/lib/mp-weixin/transform/import-template.js
@@ -0,0 +1,22 @@
+const fs = require('fs')
+const path = require('path')
+const parse = require('./template-transformer/parser')
+
+function getTemplate (content) {
+ const template = []
+ const node = parse(content)
+ node.children.forEach(node => {
+ if (node.name === 'template') {
+ const name = node.attribs.name
+ if (name) {
+ template.push(name)
+ }
+ }
+ })
+ return template
+}
+
+module.exports = function (filepath, options) {
+ filepath = path.join(path.dirname(options.filepath), filepath)
+ return getTemplate(fs.readFileSync(filepath, 'utf8').toString().trim())
+}
\ No newline at end of file
diff --git a/packages/uni-migration/lib/mp-weixin/transform/script-transformer.js b/packages/uni-migration/lib/mp-weixin/transform/script-transformer.js
index 27be87673dc016677243caed057be897af73d80b..37ae0f54c16587a9a5842b75b23bf8dbf2ee2515 100644
--- a/packages/uni-migration/lib/mp-weixin/transform/script-transformer.js
+++ b/packages/uni-migration/lib/mp-weixin/transform/script-transformer.js
@@ -1,16 +1,46 @@
const fs = require('fs')
+const importTemplate = require('./import-template')
-function transformScript(content, route, code) {
+function transformScript (content, route, code) {
return `${code}
global['__wxRoute'] = '${route}'
${content}
export default global['__wxComponents']['${route}']`
}
+function genJsCode(components, code, state) {
+ const wxTemplateComponentProps = '__wxTemplateComponentProps'
+ const props = state.props
+ const importCode = []
+ const propsCode = []
+ const componentsCode = []
+ components.forEach((node, index) => {
+ const src = node.attribs.src
+ const templates = importTemplate(src, state)
+ const identifier = `__wxTemplateComponent${index}`
+ importCode.push(`import ${identifier} from '${src.replace(/.wxml$/, '.vue')}'`)
+ templates.forEach(template => {
+ // TODO 改为在 template 编译时静态分析
+ propsCode.push(`${wxTemplateComponentProps}['${template}'] && ${wxTemplateComponentProps}['${template}'].forEach(prop => ${identifier}.props[prop] = {type: null})`)
+ componentsCode.push(`'${template}' : ${identifier}`)
+ })
+ })
+
+ return components.length ? `
+const ${wxTemplateComponentProps} = ${JSON.stringify(props)}
+${importCode.join('\n')}
+${propsCode.join('\n')}
+${code.trim().replace(/\}\}$/, '')},${componentsCode.join(',')}}}
+`: code
+}
+
module.exports = {
transformScript,
transformScriptFile(filepath, code, options, deps) {
let content = ''
+ if (options.components.length) {
+ code = genJsCode(options.components, code, options)
+ }
if (!fs.existsSync(filepath)) {
content = `
Component({})
@@ -21,4 +51,4 @@ Component({})
}
return transformScript(content, options.route, code, options)
}
-}
+}
diff --git a/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/generate.js b/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/generate.js
index 2d0247df339bcb8a81382ad5aaee7472506f55e5..bb6d0217ef5e2c867ae1477c342cbef9d50f6529 100644
--- a/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/generate.js
+++ b/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/generate.js
@@ -62,4 +62,4 @@ module.exports = function generate(node, state) {
`${genChildren(node).trim()}`,
...genWxs(state.wxs, state)
]
-}
+}
diff --git a/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/index.js b/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/index.js
index 3ada8a2a23d20185a337137f28dadb6a04236a9f..f38e828bf7a34aa727d0824d7c574b92a32170d9 100644
--- a/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/index.js
+++ b/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/index.js
@@ -3,6 +3,12 @@ const generate = require('./generate')
module.exports = function transform(ast, options) {
options.wxs = []
- options.shouldWrapper = options.shouldWrapper || function noop() {}
+ // wxml 中使用 import 导入的组件
+ options.components = []
+ // wxml 中使用 声明的模板
+ options.templates = []
+ // wxml 中 分析得到的 props
+ options.props = {}
+ options.shouldWrapper = options.shouldWrapper || function noop () { }
return generate(traverse(ast, options), options)
-}
+}
diff --git a/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/traverse.js b/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/traverse.js
index fc1a5b0d46d1d5da5804a9174e9f5a3f4d151fe8..cd89c4f048a5e30a5fe52915b6b856fc04b92e28 100644
--- a/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/traverse.js
+++ b/packages/uni-migration/lib/mp-weixin/transform/template-transformer/transform/traverse.js
@@ -1,6 +1,7 @@
const {
parse
} = require('mustache')
+const recast = require('recast')
const TAGS = [
'ad',
@@ -163,8 +164,12 @@ function transformEvent(name, value, attribs, state) {
event = transformEventName(name.replace(captureCatchRE, ''), state) + '.stop.prevent.capture'
}
if (event !== name) {
- let newValue = parseMustache(value, true)
- if (newValue !== value) {
+ // 模板 中用到的方法在其父组件
+ let newValue = parseMustache(value, !state.isTemplate)
+ if (state.isTemplate) {
+ // TODO 改为运行时判断
+ newValue = `_$self.$parent${process.env.UNI_PLATFORM === 'h5' ? '.$parent' : ''}[(${newValue})]($event)`
+ } else if (newValue !== value) {
newValue = `_$self[(${newValue})||'_$noop']($event)`
}
attribs[event] = newValue
@@ -201,9 +206,11 @@ function transformAttrs(node, state) {
}
transformFor(attribs)
const isComponent = !TAGS.includes(node.name)
+ const isTemplate = state.templates.length
Object.keys(attribs).forEach(name => {
transformAttr(name, attribs[name], attribs, {
- isComponent
+ isComponent,
+ isTemplate
})
})
}
@@ -212,7 +219,40 @@ function transformChildren(node, state) {
node.children = node.children.filter(childNode => transformNode(childNode, state))
}
+function transformTemplate(node, state) {
+ const attribs = node.attribs
+ if (attribs.name) {
+ const name = attribs.name
+ // 用于处理一个 wxml 文件内包含多个 template
+ attribs['v-if'] = `wxTemplateName === '${name}'`
+ delete attribs.name
+ state.templates.push(name)
+ } else if (attribs.is) {
+ const name = attribs.is
+ delete attribs.is
+ node.name = name
+ attribs['wx-template-name'] = name
+ const data = attribs.data
+ if (data && data.indexOf('{{') !== -1) {
+ const object = `{${parseMustache(data)}}`
+ attribs['v-bind'] = object
+ const ast = recast.parse(`const object = ${object}`)
+ const props = state.props[name] || ['wxTemplateName']
+ ast.program.body[0].declarations[0].init.properties.forEach(property => props.push(property.key.name))
+ state.props[name] = [...new Set(props)]
+ delete attribs.data
+ }
+ }
+}
+
function transformNode(node, state) {
+ if (node.name === 'import') {
+ state.components.push(node)
+ return false
+ }
+ if (node.name === 'template') {
+ transformTemplate(node, state)
+ }
if (node.name === 'wxs') {
state.wxs.push(node)
return false
@@ -227,4 +267,4 @@ function transformNode(node, state) {
module.exports = function traverse(node, state) {
transformNode(node, state)
return node
-}
+}
diff --git a/packages/uni-migration/package.json b/packages/uni-migration/package.json
index 0f38e54387886a28eac77fcfaf6ace4f0eae8a79..9448ff0ddb9f0c19eafc4dc97e5317973fdf649e 100644
--- a/packages/uni-migration/package.json
+++ b/packages/uni-migration/package.json
@@ -25,6 +25,7 @@
"commander": "^4.0.1",
"fs-extra": "^8.1.0",
"mustache": "^3.1.0",
- "stricter-htmlparser2": "^3.9.6"
+ "stricter-htmlparser2": "^3.9.6",
+ "recast": "*"
}
}