diff --git a/packages/uni-cli-shared/__tests__/usingComponents.spec.ts b/packages/uni-cli-shared/__tests__/usingComponents.spec.ts index 408429471d6..ae105ae651b 100644 --- a/packages/uni-cli-shared/__tests__/usingComponents.spec.ts +++ b/packages/uni-cli-shared/__tests__/usingComponents.spec.ts @@ -301,9 +301,10 @@ export function createApp() { `const _easycom_test = ()=>import('${inputDir}/components/test/test.vue')` ) }) - test(`recursion`, async () => { - await testLocal( - ` + describe(`recursion`, () => { + test('base', async () => { + await testLocal( + ` const _sfc_main = { }; const __BINDING_COMPONENTS__ = '{"index":{"name":"_component_index","type":"unknown"}}'; @@ -314,14 +315,16 @@ export function createApp() { import _export_sfc from "plugin-vue:export-helper"; export default /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]); `, - { - index: '/pages/index/index', - }, - `` - ) + { + index: '/pages/index/index', + }, + `` + ) + }) - await testLocal( - `import { defineComponent as _defineComponent } from "vue"; + test('use defineComponent', async () => { + await testLocal( + `import { defineComponent as _defineComponent } from "vue"; const __BINDING_COMPONENTS__ = '{"test":{"name":"test","type":"unknown"}}'; export default /* @__PURE__ */ _defineComponent({ @@ -334,14 +337,16 @@ export function createApp() { }); import "${inputDir}/pages/index/index.vue?vue&type=style&index=0&lang.css"; `, - { - test: '/pages/index/index', - }, - `` - ) + { + test: '/pages/index/index', + }, + `` + ) + }) - await testLocal( - `import { defineComponent as _defineComponent } from "vue"; + test('export variable', async () => { + await testLocal( + `import { defineComponent as _defineComponent } from "vue"; const __BINDING_COMPONENTS__ = '{"test":{"name":"test","type":"unknown"}}'; const component = _defineComponent({ __name: "test", @@ -356,11 +361,32 @@ export function createApp() { import "${inputDir}/pages/index/index.vue?vue&type=style&index=0&lang.css"; `, - { - test: '/pages/index/index', - }, - `` - ) + { + test: '/pages/index/index', + }, + `` + ) + }) + test('use plugin-vue:export-helper', async () => { + await testLocal( + ` + const _sfc_main = { + __name: 'Test' + }; + const __BINDING_COMPONENTS__ = '{"test":{"name":"_component_test","type":"unknown"}}'; + function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { + return {}; + } + import "${filename}?vue&type=style&index=0&lang.css"; + import _export_sfc from "plugin-vue:export-helper"; + export default /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]); + `, + { + test: '/pages/index/index', + }, + `` + ) + }) }) }) }) diff --git a/packages/uni-cli-shared/src/mp/usingComponents.ts b/packages/uni-cli-shared/src/mp/usingComponents.ts index 97636fbe1b5..71cead012b1 100644 --- a/packages/uni-cli-shared/src/mp/usingComponents.ts +++ b/packages/uni-cli-shared/src/mp/usingComponents.ts @@ -8,13 +8,14 @@ import { type Statement, type StringLiteral, assertExportDefaultDeclaration, - assertIdentifier, isBlockStatement, isCallExpression, isExportDefaultDeclaration, + isExpression, isIdentifier, isIfStatement, isImportDeclaration, + isImportDefaultSpecifier, isImportSpecifier, isMemberExpression, isObjectExpression, @@ -211,14 +212,13 @@ function parseVueComponentName(filename: string) { if (!exportDefaultDecliaration) return name - // 获取vue的defineComponent导入变量名 + // 获取vue的defineComponent导入变量名和plugin-vue:export-helper默认导入的本地变量名 let defineComponentLocalName: string | null = null + let exportHelperLocalName: string | null = null for (const node of ast.body) { - if ( - isImportDeclaration(node) && - isStringLiteral(node.source, { value: 'vue' }) - ) { + if (!isImportDeclaration(node)) continue + if (isStringLiteral(node.source, { value: 'vue' })) { const importSpecifer = node.specifiers.find( (specifer) => isImportSpecifier(specifer) && @@ -227,20 +227,37 @@ function parseVueComponentName(filename: string) { if (isImportSpecifier(importSpecifer)) { defineComponentLocalName = importSpecifer.local.name } + } else if ( + isStringLiteral(node.source, { value: 'plugin-vue:export-helper' }) + ) { + const importSpecifer = node.specifiers.find((specifer) => + isImportDefaultSpecifier(specifer) + ) + if (isImportDefaultSpecifier(importSpecifer)) { + exportHelperLocalName = importSpecifer.local.name + } } } + let { declaration } = exportDefaultDecliaration + // 如果默认导出调用plugin-vue:export-helper默认导入的方法则取方法的第一个参数 + if ( + exportHelperLocalName && + isCallExpression(declaration) && + isIdentifier(declaration.callee, { name: exportHelperLocalName }) && + isExpression(declaration.arguments[0]) + ) { + declaration = declaration.arguments[0] + } + // 获取组件定义对象 let defineComponentDeclaration: ObjectExpression | null = null - let { declaration } = exportDefaultDecliaration - - // 如果默认导出了变量则尝试查找该变量 + // 如果declaration是变量则尝试查找该变量 if (isIdentifier(declaration)) { const { name } = declaration for (const node of ast.body) { if (isVariableDeclaration(node)) { - assertIdentifier(declaration) const declarator = node.declarations.find((declarator) => isIdentifier(declarator.id, { name }) ) @@ -274,7 +291,7 @@ function parseVueComponentName(filename: string) { /(__)?name/.test(prop.key.name) && isStringLiteral(prop.value) ) { - return prop.value.value + return prop.value.value || name } } return name