diff --git a/packages/uni-cli-shared/src/mp/event.ts b/packages/uni-cli-shared/src/mp/event.ts index dcf17249254b8256451cd72029c8d30f53d29bdf..22fa8cc23067896d3db74c309802e22f0d113757 100644 --- a/packages/uni-cli-shared/src/mp/event.ts +++ b/packages/uni-cli-shared/src/mp/event.ts @@ -25,6 +25,9 @@ export function formatMiniProgramEvent( } function isSimpleExpr(name: string) { + if (name.startsWith('_')) { + return false + } if (name.indexOf('-') > -1) { return false } diff --git a/packages/uni-cli-shared/src/mp/template.ts b/packages/uni-cli-shared/src/mp/template.ts index 6611fd74e88661861ab5ebc32f82a55c9322848c..1e125fe890cdccec8a0a879c5ecdf5cae5c60178 100644 --- a/packages/uni-cli-shared/src/mp/template.ts +++ b/packages/uni-cli-shared/src/mp/template.ts @@ -1,5 +1,26 @@ -import { LINEFEED } from '@dcloudio/uni-shared' +import { EmittedAsset } from 'rollup' +import { isComponentTag, LINEFEED } from '@dcloudio/uni-shared' +import { + createSimpleExpression, + ElementTypes, + isCoreComponent, + locStub, + NodeTypes, + RootNode, + TemplateChildNode, + TransformContext, +} from '@vue/compiler-core' +export interface MiniProgramCompilerOptions { + slot: { + fallback: boolean + } + filter?: { + lang: string + } + directive: string + emitFile?: (emittedFile: EmittedAsset) => string +} export interface MiniProgramFilterOptions { id: string type: 'wxs' @@ -65,3 +86,30 @@ export function addMiniProgramTemplateFilter( templateFiltersCache.set(filename, [filter]) } } + +export function addComponentBindLink( + node: RootNode | TemplateChildNode, + context: TransformContext +) { + if ( + node.type === NodeTypes.ELEMENT && + node.tagType === ElementTypes.COMPONENT + ) { + const { tag } = node + if ( + isComponentTag(tag) || + isCoreComponent(tag) || + context.isBuiltInComponent(tag) + ) { + return + } + node.props.push({ + type: NodeTypes.DIRECTIVE, + name: 'on', + modifiers: [], + loc: locStub, + arg: createSimpleExpression('__l', true), + exp: createSimpleExpression('__l', true), + }) + } +} diff --git a/packages/uni-cli-shared/src/vite/index.ts b/packages/uni-cli-shared/src/vite/index.ts index 4a0a0b8e9f830631d629df02963b99b1ab0525b3..ef8f157366ee5d7fddf9e19b2dc5933dff90ef90 100644 --- a/packages/uni-cli-shared/src/vite/index.ts +++ b/packages/uni-cli-shared/src/vite/index.ts @@ -1,5 +1,5 @@ import type { Plugin } from 'vite' -import type { EmittedFile } from 'rollup' +import type { EmittedAsset } from 'rollup' import type { ParserOptions } from '@vue/compiler-core' import type { CompilerOptions, TemplateCompiler } from '@vue/compiler-sfc' import { UniViteCopyPluginOptions } from './plugins/copy' @@ -16,7 +16,7 @@ interface UniVitePluginUniOptions { compiler?: TemplateCompiler compilerOptions?: { miniProgram?: { - emitFile?: (emittedFile: EmittedFile) => string + emitFile?: (emittedFile: EmittedAsset) => string } isNativeTag: ParserOptions['isNativeTag'] isCustomElement: ParserOptions['isCustomElement'] diff --git a/packages/uni-mp-compiler/__tests__/component.spec.ts b/packages/uni-mp-compiler/__tests__/component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..54190261d63e017d60ec49d238b1e9f531b8a698 --- /dev/null +++ b/packages/uni-mp-compiler/__tests__/component.spec.ts @@ -0,0 +1,17 @@ +import { addComponentBindLink } from '@dcloudio/uni-cli-shared' +import { assert } from './testUtils' + +describe('compiler: transform component', () => { + test('basic', () => { + assert( + ``, + ``, + `(_ctx, _cache) => { + return {} +}`, + { + nodeTransforms: [addComponentBindLink as any], + } + ) + }) +}) diff --git a/packages/uni-mp-compiler/src/compile.ts b/packages/uni-mp-compiler/src/compile.ts index 319735f7dd55ac5f6db7ba0490e5ca8df1ed09e8..46a68b7f83b5bd4ce67cba55f71269f48fec245b 100644 --- a/packages/uni-mp-compiler/src/compile.ts +++ b/packages/uni-mp-compiler/src/compile.ts @@ -1,7 +1,7 @@ import fs from 'fs' import { baseParse } from '@vue/compiler-core' import { isString, extend } from '@vue/shared' -import { parseFilterNames } from '@dcloudio/uni-cli-shared' +import { hash, parseFilterNames } from '@dcloudio/uni-cli-shared' import { generate } from './codegen' import { CompilerOptions } from './options' import { DirectiveTransform, NodeTransform, transform } from './transform' @@ -45,12 +45,18 @@ export function baseCompile(template: string, options: CompilerOptions = {}) { prefixIdentifiers, skipTransformIdentifier: options.skipTransformIdentifier === true, }) - if (options.filename && !options.filters && options.miniProgram?.filter) { - options.filters = parseFilters( - options.miniProgram.filter.lang, - options.filename - ) + + options.vueId = genVueId(options) + + if (options.filename) { + if (options.filters && options.miniProgram?.filter) { + options.filters = parseFilters( + options.miniProgram.filter.lang, + options.filename + ) + } } + const context = transform( ast, extend({}, options, { @@ -86,6 +92,19 @@ export function baseCompile(template: string, options: CompilerOptions = {}) { return result } +function genVueId(options: CompilerOptions) { + if (options.vueId) { + return options.vueId + } + if (options.scopeId) { + return options.scopeId.replace('data-v-', '') + } + if (options.filename) { + return hash(options.filename) + } + return '' +} + function parseFilters(lang: string, filename: string) { filename = filename.split('?')[0] if (fs.existsSync(filename)) { diff --git a/packages/uni-mp-compiler/src/options.ts b/packages/uni-mp-compiler/src/options.ts index 8b9e4c514b094f9b1e2de11607e2dbd343fef8ac..02894e15aff5830383ea47055eea3fb4d70989b6 100644 --- a/packages/uni-mp-compiler/src/options.ts +++ b/packages/uni-mp-compiler/src/options.ts @@ -1,5 +1,6 @@ import { ParserPlugin } from '@babel/parser' import { Expression, ObjectProperty, SpreadElement } from '@babel/types' +import { MiniProgramCompilerOptions } from '@dcloudio/uni-cli-shared' import { BindingMetadata, CompilerError, RootNode } from '@vue/compiler-core' import IdentifierGenerator from './identifier' import { @@ -45,6 +46,7 @@ interface SharedTransformCodegenOptions { export interface TransformOptions extends SharedTransformCodegenOptions, ErrorHandlingOptions { + vueId?: string | null scopeId?: string | null filters?: string[] cacheHandlers?: boolean @@ -76,38 +78,18 @@ export interface CodegenVForScope export type CodegenScope = CodegenRootScope | CodegenVIfScope | CodegenVForScope -interface EmittedFile { - fileName?: string - name?: string - source?: string | Uint8Array - type: 'asset' -} - export interface CodegenOptions extends SharedTransformCodegenOptions { mode?: 'module' | 'function' scopeId?: string | null runtimeModuleName?: string runtimeGlobalName?: string - miniProgram?: { - slot: { - fallback: boolean - } - filter?: { - lang: string - } - directive: string - emitFile?: (emittedFile: EmittedFile) => string - } + miniProgram?: MiniProgramCompilerOptions } -export interface TemplateCodegenOptions { - slot: { - fallback: boolean - } +export interface TemplateCodegenOptions + extends Omit { scopeId?: string | null filename: string - directive: string - emitFile: (emittedFile: EmittedFile) => string } export type CompilerOptions = ParserOptions & TransformOptions & CodegenOptions diff --git a/packages/uni-mp-compiler/src/template/codegen.ts b/packages/uni-mp-compiler/src/template/codegen.ts index 874f31f4376c1c2b8d18a93f9f2ed9e35633bab9..04825f16cf53ae4ea334ae5ebdcf3d55e986fddb 100644 --- a/packages/uni-mp-compiler/src/template/codegen.ts +++ b/packages/uni-mp-compiler/src/template/codegen.ts @@ -1,6 +1,7 @@ import { hyphenate } from '@vue/shared' import { formatMiniProgramEvent } from '@dcloudio/uni-cli-shared' import { + ComponentNode, DirectiveNode, ElementNode, ElementTypes, @@ -9,7 +10,9 @@ import { NodeTypes, RootNode, SimpleExpressionNode, + SlotOutletNode, TemplateChildNode, + TemplateNode, TextNode, } from '@vue/compiler-core' import { TemplateCodegenOptions } from '../options' @@ -43,7 +46,7 @@ export function generate( children.forEach((node) => { genNode(node, context) }) - emitFile({ type: 'asset', fileName: filename, source: context.code }) + emitFile!({ type: 'asset', fileName: filename, source: context.code }) } export function genNode( @@ -69,7 +72,6 @@ export function genNode( } else if (isLazyElement(node)) { return genLazyElement(node, context) } - return genElement(node, context) } } @@ -109,7 +111,7 @@ function genVFor( } } -function genSlot(node: ElementNode, context: TemplateCodegenContext) { +function genSlot(node: SlotOutletNode, context: TemplateCodegenContext) { if (!node.children.length) { return genElement(node, context) } @@ -152,7 +154,7 @@ function findSlotName(node: ElementNode) { } } -function genTemplate(node: ElementNode, context: TemplateCodegenContext) { +function genTemplate(node: TemplateNode, context: TemplateCodegenContext) { const slotName = findSlotName(node) if (slotName) { /** @@ -165,11 +167,12 @@ function genTemplate(node: ElementNode, context: TemplateCodegenContext) { //