You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
7.2 KiB
187 lines
7.2 KiB
"use strict"; |
|
Object.defineProperty(exports, "__esModule", { value: true }); |
|
exports.rewriteSlot = void 0; |
|
const compiler_core_1 = require("@vue/compiler-core"); |
|
const shared_1 = require("@vue/shared"); |
|
const uni_shared_1 = require("@dcloudio/uni-shared"); |
|
const runtimeHelpers_1 = require("../runtimeHelpers"); |
|
const codegen_1 = require("../codegen"); |
|
const transform_1 = require("../transform"); |
|
const transformElement_1 = require("./transformElement"); |
|
const utils_1 = require("./utils"); |
|
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared"); |
|
const __1 = require(".."); |
|
const ast_1 = require("../ast"); |
|
function rewriteSlot(node, context) { |
|
let slotName = `"${uni_shared_1.SLOT_DEFAULT_NAME}"`; |
|
let hasOtherDir = false; |
|
const nonNameProps = []; |
|
const { props } = node; |
|
// 默认插槽强制设置name |
|
if (!(0, compiler_core_1.findProp)(node, 'name')) { |
|
props.unshift((0, uni_cli_shared_1.createAttributeNode)('name', 'default')); |
|
} |
|
for (let i = 0; i < props.length; i++) { |
|
const p = props[i]; |
|
if (p.type === 6 /* NodeTypes.ATTRIBUTE */) { |
|
if (p.value) { |
|
if (p.name === 'name') { |
|
p.value.content = (0, uni_shared_1.dynamicSlotName)(p.value.content); |
|
slotName = JSON.stringify(p.value.content); |
|
} |
|
else { |
|
p.name = (0, shared_1.camelize)(p.name); |
|
nonNameProps.push(p); |
|
} |
|
} |
|
} |
|
else { |
|
if (p.name !== 'bind') { |
|
hasOtherDir = true; |
|
} |
|
if (p.name === 'bind' && (0, compiler_core_1.isStaticArgOf)(p.arg, 'name')) { |
|
if (p.exp) { |
|
slotName = (0, compiler_core_1.createCompoundExpression)([ |
|
context.helperString(__1.DYNAMIC_SLOT) + '(', |
|
p.exp, |
|
')', |
|
]); |
|
let slotKey; |
|
const keys = parseVForKeyAlias(context); |
|
if (keys.length) { |
|
const babelNode = (0, ast_1.parseExpr)(p.exp, context); |
|
// 在 v-for 中,判断是否插槽名使用 v-for 的 key 变量 |
|
if (babelNode && (0, utils_1.isReferencedByIds)(babelNode, keys)) { |
|
slotKey = parseScopedSlotKey(context); |
|
} |
|
} |
|
p.exp = (0, utils_1.rewriteExpression)((0, compiler_core_1.createCompoundExpression)([ |
|
context.helperString(__1.DYNAMIC_SLOT) + '(', |
|
p.exp, |
|
slotKey ? `+'-'+` + slotKey : '', |
|
')', |
|
]), context); |
|
} |
|
} |
|
else { |
|
if (p.name === 'bind' && p.arg && (0, compiler_core_1.isStaticExp)(p.arg)) { |
|
p.arg.content = (0, shared_1.camelize)(p.arg.content); |
|
} |
|
nonNameProps.push(p); |
|
} |
|
} |
|
} |
|
if (hasOtherDir) { |
|
context.onError((0, compiler_core_1.createCompilerError)(36 /* ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET */, node.loc)); |
|
} |
|
if (nonNameProps.length > 0) { |
|
(0, transformElement_1.processProps)(node, context, nonNameProps); |
|
const properties = []; |
|
nonNameProps.forEach((prop) => { |
|
const property = transformProperty(prop, context); |
|
property && properties.push(property); |
|
}); |
|
if (properties.length) { |
|
transformScopedSlotName(node, context); |
|
const vForIndexAlias = parseVForIndexAlias(context); |
|
(0, utils_1.rewriteExpression)((0, compiler_core_1.createCompoundExpression)([ |
|
context.helperString(runtimeHelpers_1.RENDER_SLOT) + '(', |
|
slotName, |
|
',', |
|
`{${properties.join(',')}}`, |
|
`${vForIndexAlias ? ',' + parseScopedSlotKey(context) : ''}`, |
|
')', |
|
]), context); |
|
} |
|
else { |
|
// 非作用域默认插槽直接移除命名 |
|
if (slotName === `"${uni_shared_1.SLOT_DEFAULT_NAME}"`) { |
|
(0, utils_1.removeAttribute)(node, 'name'); |
|
} |
|
} |
|
} |
|
else { |
|
// 非作用域默认插槽直接移除命名 |
|
if (slotName === `"${uni_shared_1.SLOT_DEFAULT_NAME}"`) { |
|
(0, utils_1.removeAttribute)(node, 'name'); |
|
} |
|
} |
|
} |
|
exports.rewriteSlot = rewriteSlot; |
|
function parseVForIndexAlias(context) { |
|
let { currentScope } = context; |
|
while (currentScope) { |
|
if ((0, transform_1.isVForScope)(currentScope) && !(0, transform_1.isScopedSlotVFor)(currentScope)) { |
|
return currentScope.indexAlias; |
|
} |
|
currentScope = currentScope.parent; |
|
} |
|
} |
|
function transformScopedSlotName(node, context) { |
|
if (!context.miniProgram.slot.dynamicSlotNames) { |
|
return; |
|
} |
|
const slotKey = parseScopedSlotKey(context); |
|
if (!slotKey) { |
|
return; |
|
} |
|
const nameProps = (0, compiler_core_1.findProp)(node, 'name'); |
|
if (nameProps && nameProps.type === 6 /* NodeTypes.ATTRIBUTE */ && nameProps.value) { |
|
const { props } = node; |
|
props.splice(props.indexOf(nameProps), 1, createScopedSlotDirectiveNode(nameProps.value.content, slotKey, context)); |
|
} |
|
} |
|
function createScopedSlotDirectiveNode(name, slotKey, context) { |
|
const dir = (0, uni_cli_shared_1.createBindDirectiveNode)('name', (0, utils_1.rewriteExpression)((0, compiler_core_1.createSimpleExpression)(`"${name}-"+` + slotKey), context) |
|
.content); |
|
// 存储原始的 slot 名称 |
|
dir.slotName = name; |
|
return dir; |
|
} |
|
function parseVForKeyAlias(context) { |
|
let { currentScope } = context; |
|
const keys = []; |
|
while (currentScope) { |
|
if ((0, transform_1.isVForScope)(currentScope) && !(0, transform_1.isScopedSlotVFor)(currentScope)) { |
|
keys.push(currentScope.keyAlias); |
|
} |
|
currentScope = currentScope.parent; |
|
} |
|
return keys; |
|
} |
|
function parseVForIndexes(context) { |
|
let { currentScope } = context; |
|
const indexes = []; |
|
while (currentScope) { |
|
if ((0, transform_1.isVForScope)(currentScope) && !(0, transform_1.isScopedSlotVFor)(currentScope)) { |
|
indexes.push(currentScope.indexAlias); |
|
} |
|
currentScope = currentScope.parent; |
|
} |
|
return indexes; |
|
} |
|
function parseSlotKeyByVForIndexes(indexes) { |
|
return indexes.reverse().join(`+'-'+`); |
|
} |
|
function parseScopedSlotKey(context) { |
|
const indexes = parseVForIndexes(context); |
|
const inFor = !!indexes.length; |
|
if (inFor) { |
|
return parseSlotKeyByVForIndexes(indexes); |
|
} |
|
} |
|
function transformProperty(dir, _) { |
|
if ((0, uni_cli_shared_1.isDirectiveNode)(dir)) { |
|
if (!dir.arg || !dir.exp) { |
|
return; |
|
} |
|
const isStaticArg = dir.arg.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ && dir.arg.isStatic; |
|
if (isStaticArg) { |
|
return `${dir.arg.content}:${(0, codegen_1.genExpr)(dir.exp)}`; |
|
} |
|
return `[${(0, codegen_1.genExpr)(dir.arg)}||'']:${(0, codegen_1.genExpr)(dir.exp)}`; |
|
} |
|
if (dir.value) { |
|
return `${dir.name}:${(0, codegen_1.genExpr)(dir.value)}`; |
|
} |
|
}
|
|
|