uni-ticket-system/node_modules/@dcloudio/uni-mp-compiler/dist/transforms/vSlot.js
2023-12-05 10:11:10 +08:00

275 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createVSlotCallExpression = exports.rewriteScopedSlotVForScope = exports.findCurrentPath = exports.findSlotName = exports.rewriteVSlot = exports.transformSlot = void 0;
const types_1 = require("@babel/types");
const shared_1 = require("@vue/shared");
const compiler_core_1 = require("@vue/compiler-core");
const uni_shared_1 = require("@dcloudio/uni-shared");
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
const runtimeHelpers_1 = require("../runtimeHelpers");
const ast_1 = require("../ast");
const codegen_1 = require("../codegen");
const transform_1 = require("../transform");
const utils_1 = require("./utils");
const vFor_1 = require("./vFor");
const runtimeHelpers_2 = require("../runtimeHelpers");
const transformSlot = (node, context) => {
if (!(0, uni_cli_shared_1.isUserComponent)(node, context)) {
return;
}
const { tag, children } = node;
const slots = new Set();
const onComponentSlot = (0, compiler_core_1.findDir)(node, 'slot', true);
const implicitDefaultChildren = [];
const isMiniProgramComponent = context.isMiniProgramComponent(tag);
for (let i = 0; i < children.length; i++) {
const slotElement = children[i];
let slotDir;
if (!(0, compiler_core_1.isTemplateNode)(slotElement) ||
!(slotDir = (0, compiler_core_1.findDir)(slotElement, 'slot', true))) {
// not a <template v-slot>, skip.
if (slotElement.type !== 3 /* NodeTypes.COMMENT */) {
implicitDefaultChildren.push(slotElement);
}
continue;
}
if (onComponentSlot) {
// already has on-component slot - this is incorrect usage.
context.onError((0, compiler_core_1.createCompilerError)(37 /* ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE */, slotDir.loc));
break;
}
if (!slotDir.arg) {
// v-slot => v-slot:default
slotDir.arg = (0, compiler_core_1.createSimpleExpression)('default', true);
}
const slotName = transformTemplateSlotElement(slotDir, slotElement, node, context);
// 小程序组件默认插槽,直接移除<template #default>节点
if (isMiniProgramComponent) {
if (slotName === 'default' && slotElement.children.length === 1) {
children.splice(i, 1, slotElement.children[0]);
}
continue;
}
if (slotName) {
slots.add(slotName);
}
}
if (isMiniProgramComponent) {
return;
}
if (implicitDefaultChildren.length) {
slots.add(uni_shared_1.SLOT_DEFAULT_NAME);
}
if (onComponentSlot) {
// <unicloud-db v-slot:default="{data, loading, error, options}"/>
// => <unicloud-db collection=""><template v-slot:default="{data, loading, error, options}"/></unicloud-db>
slots.add(uni_shared_1.SLOT_DEFAULT_NAME);
const templateNode = createTemplateNode(onComponentSlot, implicitDefaultChildren);
transformTemplateSlotElement(onComponentSlot, templateNode, node, context);
node.children = [templateNode];
}
// 不支持 $slots, 则自动补充 props
if (slots.size && !context.miniProgram.slot.$slots) {
const slotsArr = [...slots];
const hasDynamic = slotsArr.find((name) => !(0, shared_1.isString)(name));
let value;
if (hasDynamic) {
const children = [];
const len = slotsArr.length - 1;
slotsArr.forEach((name, index) => {
if ((0, shared_1.isString)(name)) {
children.push(`'${(0, uni_shared_1.dynamicSlotName)(name)}'`);
}
else {
children.push(name);
}
if (index < len) {
children.push(',');
}
});
value = (0, compiler_core_1.createCompoundExpression)([
context.helperString(runtimeHelpers_2.DYNAMIC_SLOT) + '([',
...children,
'])',
]);
}
else {
value = `[${slotsArr
.map((name) => `'${(0, uni_shared_1.dynamicSlotName)(name)}'`)
.join(',')}]`;
}
node.props.unshift((0, uni_cli_shared_1.createBindDirectiveNode)(utils_1.ATTR_VUE_SLOTS, value));
}
};
exports.transformSlot = transformSlot;
function rewriteVSlot(dir, context) {
dir.arg = (0, utils_1.rewriteExpression)((0, compiler_core_1.createCompoundExpression)([
context.helperString(runtimeHelpers_2.DYNAMIC_SLOT) + '(',
dir.arg,
')',
]), context);
}
exports.rewriteVSlot = rewriteVSlot;
function transformTemplateSlotElement(slotDir, slotTemplate, slotComponent, context) {
const slotName = findSlotName(slotDir);
if (!slotName) {
return;
}
const { exp } = slotDir;
// non scoped slots
if (!exp) {
return slotName;
}
// empty
if (exp.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ && !exp.content.trim()) {
return slotName;
}
// 使用vFor来简单处理scoped slot作用域问题
slotTemplate.children = [
createVForTemplate(slotTemplate, { name: slotName, value: (0, codegen_1.genExpr)(exp), slotComponent }, context),
];
if (context.miniProgram.slot.dynamicSlotNames) {
// 已经在 vFor 中补充 slot故需要移除 slotTemplate 中的
const index = slotTemplate.props.indexOf(slotDir);
if (index > -1) {
slotTemplate.props.splice(index, 1);
}
}
// v-slot="slotProps" => v-slot 避免 transformIdentifier 生成 slotProps 的变量声明
slotDir.exp = undefined;
return slotName;
}
function createTemplateNode(slotDir, children) {
return {
type: 1 /* NodeTypes.ELEMENT */,
tag: 'template',
tagType: 3 /* ElementTypes.TEMPLATE */,
loc: compiler_core_1.locStub,
isSelfClosing: false,
codegenNode: undefined,
ns: 0,
props: [slotDir],
children,
};
}
function findSlotName(slotDir) {
if (!slotDir.arg) {
return uni_shared_1.SLOT_DEFAULT_NAME;
}
if ((0, compiler_core_1.isStaticExp)(slotDir.arg)) {
return slotDir.arg.content;
}
return slotDir.arg;
}
exports.findSlotName = findSlotName;
function findCurrentVForValueAlias(context) {
let scope = context.currentScope;
while (scope) {
if ((0, transform_1.isVForScope)(scope)) {
return scope.valueAlias;
}
scope = scope.parent;
}
return '';
}
function createVForTemplate(slotElement, { name, value, slotComponent, }, context) {
const slotName = 's' + context.scopes.vFor;
const keyProp = (0, uni_cli_shared_1.createBindDirectiveNode)('key', 'i' + context.scopes.vFor);
const source = (0, shared_1.isString)(name) ? `'${name}'` : (0, codegen_1.genExpr)(name);
const vForProp = {
type: 7 /* NodeTypes.DIRECTIVE */,
name: 'for',
loc: compiler_core_1.locStub,
modifiers: [],
arg: undefined,
exp: (0, compiler_core_1.createSimpleExpression)(`(${value}, ${slotName}) in ${utils_1.SCOPED_SLOT_IDENTIFIER}(${source}, ${findCurrentVForValueAlias(context) || `''`})`),
};
const props = [vForProp, keyProp];
if (context.miniProgram.slot.dynamicSlotNames) {
props.push((0, uni_cli_shared_1.createBindDirectiveNode)('slot', slotName));
}
return {
loc: slotElement.loc,
ns: 0,
tag: 'template',
type: 1 /* NodeTypes.ELEMENT */,
tagType: 3 /* ElementTypes.TEMPLATE */,
props,
isSelfClosing: false,
codegenNode: undefined,
children: slotElement.children,
slotComponent,
};
}
const slotNameRE = /\('(.*)',/;
/**
* ('default','') => default
* @param source
* @returns
*/
function findCurrentSlotName(source) {
return (0, types_1.stringLiteral)((0, uni_shared_1.dynamicSlotName)(source.children[1].match(slotNameRE)[1]));
}
function createPathBinaryExpr(scope, computed = true) {
return (0, types_1.binaryExpression)('+', (0, types_1.binaryExpression)('+', (0, types_1.stringLiteral)(parseVForPath(scope.sourceAlias) + (computed ? '[' : '.')), (0, types_1.identifier)(scope.indexAlias)), (0, types_1.stringLiteral)(computed ? '].' : '.'));
}
function findCurrentPath(id, scope) {
let parent = scope.parent;
let binaryExpr = null;
while (parent) {
if ((0, transform_1.isVForScope)(parent)) {
// const computed = !isScopedSlotVFor(parent)
if (!binaryExpr) {
binaryExpr = createPathBinaryExpr(parent);
}
else {
binaryExpr = (0, types_1.binaryExpression)('+', createPathBinaryExpr(parent), binaryExpr);
}
}
parent = parent.parent;
}
return ((binaryExpr && (0, types_1.binaryExpression)('+', binaryExpr, (0, types_1.stringLiteral)(id))) ||
(0, types_1.stringLiteral)(id));
}
exports.findCurrentPath = findCurrentPath;
function findCurrentVueIdExpr(node, context) {
if (!node) {
return (0, types_1.stringLiteral)('');
}
const vueIdProp = (0, compiler_core_1.findProp)(node, utils_1.ATTR_VUE_ID);
if (vueIdProp.type === 6 /* NodeTypes.ATTRIBUTE */) {
return (0, types_1.stringLiteral)(vueIdProp.value.content);
}
return (0, ast_1.parseExpr)((0, codegen_1.genExpr)(vueIdProp.exp), context) || (0, types_1.stringLiteral)('');
}
/**
* 目前无用
* @param vForScope
* @param parentScope
* @param context
*/
function rewriteScopedSlotVForScope(vForScope, parentScope, context) {
// 生成一个新的sourceAlias用于scopedSlots
const { source, sourceExpr } = vForScope;
vForScope.sourceAlias = (0, utils_1.rewriteExpressionWithoutProperty)(source, context, sourceExpr, parentScope).content;
}
exports.rewriteScopedSlotVForScope = rewriteScopedSlotVForScope;
function parseVForPath(id) {
return id.includes('.') ? id.split('.')[1] : id;
}
function createVSlotCallExpression(slotComponent, vForScope, context) {
const { source, sourceAlias } = vForScope;
const id = parseVForPath(sourceAlias);
return (0, types_1.callExpression)((0, types_1.identifier)(context.helperString(runtimeHelpers_1.WITH_SCOPED_SLOT)), [
(0, vFor_1.createVForArrowFunctionExpression)(vForScope),
(0, types_1.objectExpression)([
// 插槽名称,数据更新 pathvueId
(0, types_1.objectProperty)((0, types_1.identifier)('name'), findCurrentSlotName(source)),
// 暂不生成 path
(0, types_1.objectProperty)((0, types_1.identifier)('path'), findCurrentPath(id, vForScope)),
(0, types_1.objectProperty)((0, types_1.identifier)('vueId'), findCurrentVueIdExpr(slotComponent, context)),
]),
]);
}
exports.createVSlotCallExpression = createVSlotCallExpression;