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.

185 lines
8.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.rewriteId = void 0;
const compiler_core_1 = require("@vue/compiler-core");
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
const runtimeHelpers_1 = require("../runtimeHelpers");
const utils_1 = require("./utils");
const transformSlot_1 = require("./transformSlot");
const transformRef_1 = require("./transformRef");
const shared_1 = require("@vue/shared");
const types_1 = require("@babel/types");
const ast_1 = require("../ast");
const codegen_1 = require("../codegen");
const builtInCustomElements = ['uni-cloud-db-element'];
const builtInComponents = ['unicloud-db'];
function rewriteId(node, context) {
const isUniElement = !(0, uni_cli_shared_1.isUserComponent)(node, context);
const origTagName = node.tag;
const isBuiltInComponent = !isUniElement && builtInComponents.includes(origTagName);
const userComponent = !(isUniElement || isBuiltInComponent);
if (userComponent) {
// TODO 目前不对用户的自定义组件支持 id 查询 UniElement
// 后续要做的话,需要考虑自定义组件内部的单节点或多节点
return;
}
const isBuiltInCustomElement = builtInCustomElements.includes(origTagName);
if (isUniElement) {
// 将内置的自定义元素转换为 view
if (isBuiltInCustomElement) {
node.props.unshift((0, uni_cli_shared_1.createAttributeNode)(utils_1.ATTR_ELEMENT_TAG, origTagName));
node.tag = 'view';
}
}
// 内置组件使用了 ref没有 id 时,自动补充一个
const refProp = (0, compiler_core_1.findProp)(node, utils_1.ATTR_VUE_REF) || (0, compiler_core_1.findProp)(node, 'ref');
let idProp = (0, compiler_core_1.findProp)(node, 'id');
if (refProp && !idProp) {
if (context.inVFor) {
// v-for 中的 ref 需要使用 v-for 的 key 作为 id
const keyAlias = (0, transformSlot_1.parseVForKeyAlias)(context);
// 微信小程序元素id必须以字母开头所以hashId不能放到前边它可能是数字开头
const id = 'r' + context.elementRefIndex++ + '-' + context.hashId + '-';
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)('id', (0, compiler_core_1.createCompoundExpression)([`'${id}'+`, keyAlias.join(`+'-'+`)])));
}
else {
const id = 'r' + context.elementRefIndex++ + '-' + context.hashId;
node.props.push((0, uni_cli_shared_1.createAttributeNode)('id', id));
}
}
else if (refProp && idProp && (0, uni_cli_shared_1.isDirectiveNode)(idProp)) {
// ref 和 id 都存在,且 id 是动态绑定的, 但是可能为空字符串。比如virtualHost绑定的id
const idPropIndex = node.props.indexOf(idProp);
node.props.splice(idPropIndex, 1);
if (idProp.exp) {
let idBindingExpr = (0, ast_1.parseExpr)(idProp.exp, context);
let genId = '';
if (context.inVFor) {
// v-for 中的 ref 需要使用 v-for 的 key 作为 id
const keyAlias = (0, transformSlot_1.parseVForKeyAlias)(context);
// 微信小程序元素id必须以字母开头所以hashId不能放到前边它可能是数字开头
genId =
'r' +
context.elementRefIndex++ +
'-' +
context.hashId +
'-' +
keyAlias.join('-');
}
else {
genId = 'r' + context.elementRefIndex++ + '-' + context.hashId;
}
// TODO context.helperString能否避免调用?
if ((0, types_1.isCallExpression)(idBindingExpr) &&
(0, types_1.isIdentifier)(idBindingExpr.callee) &&
idBindingExpr.callee.name === context.helperString(runtimeHelpers_1.GEN_UNI_ELEMENT_ID)) {
// 如果调用的是genUniElementId则直接传入自动生成的id作为第三个参数。此特性用于减小生成代码体积
idBindingExpr.arguments.push((0, types_1.stringLiteral)(genId));
}
else {
idBindingExpr = (0, types_1.conditionalExpression)((0, types_1.binaryExpression)('!==', idBindingExpr, (0, types_1.stringLiteral)('')), idBindingExpr, (0, types_1.stringLiteral)(genId));
}
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)('id', (0, compiler_core_1.createSimpleExpression)((0, codegen_1.genBabelExpr)(idBindingExpr))));
}
}
idProp = (0, compiler_core_1.findProp)(node, 'id');
if (!idProp) {
return;
}
let idOptions = origTagName;
if (isBuiltInComponent || isBuiltInCustomElement) {
idOptions = {
name: origTagName,
type: isBuiltInComponent
? 1 /* SetUniElementIdTagType.BuiltInComponent */
: 2 /* SetUniElementIdTagType.BuiltInRootElement */,
};
}
let idExprNode;
// id="test" => :id="setUniElementId('test')"
// 目前标签名有隐患,可能传入的是自定义组件名称
if ((0, uni_cli_shared_1.isAttributeNode)(idProp)) {
if (!idProp.value) {
return;
}
idExprNode = `'${idProp.value.content}'`;
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)(utils_1.ATTR_ELEMENT_ID, (0, compiler_core_1.createCompoundExpression)([
context.helperString(runtimeHelpers_1.SET_UNI_ELEMENT_ID) + '(',
idExprNode,
',',
(0, shared_1.isString)(idOptions) ? `'${idOptions}'` : JSON.stringify(idOptions),
parseUniElementRefCode(node, context),
')',
])));
}
else if (idProp.exp) {
idExprNode = idProp.exp;
const idPropIndex = node.props.indexOf(idProp);
// :id="a" => :id="setUniElementId(a)"
node.props.splice(idPropIndex, 1, (0, uni_cli_shared_1.createBindDirectiveNode)('id', (0, compiler_core_1.createCompoundExpression)([
context.helperString(runtimeHelpers_1.SET_UNI_ELEMENT_ID) + '(',
idExprNode,
',',
(0, shared_1.isString)(idOptions) ? `'${idOptions}'` : JSON.stringify(idOptions),
parseUniElementRefCode(node, context),
')',
])));
}
if (context.miniProgram.filter?.setStyle) {
// 支持通过filter来设置style
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)((0, utils_1.filterObserverName)(utils_1.ATTR_SET_ELEMENT_STYLE), (0, utils_1.filterName)(utils_1.FILTER_SET_ELEMENT_STYLE)));
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)(utils_1.ATTR_SET_ELEMENT_STYLE, ''));
// setAnimation
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)((0, utils_1.filterObserverName)(utils_1.ATTR_SET_ELEMENT_ANIMATION), (0, utils_1.filterName)(utils_1.FILTER_SET_ELEMENT_ANIMATION)));
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)(utils_1.ATTR_SET_ELEMENT_ANIMATION, ''));
if (!context.autoImportFilters.find((filter) => filter.name === utils_1.FILTER_MODULE_NAME)) {
context.autoImportFilters.push({
name: utils_1.FILTER_MODULE_NAME,
id: utils_1.FILTER_MODULE_FILE_NAME,
type: 'filter',
});
}
}
else {
// 如果没有动态绑定 style则创建一个新的
const styleProp = (0, compiler_core_1.findProp)(node, 'style', true, true);
if (!styleProp) {
node.props.push((0, uni_cli_shared_1.createBindDirectiveNode)('style', (0, compiler_core_1.createCompoundExpression)([
context.helperString(runtimeHelpers_1.SET_UNI_ELEMENT_STYLE) + '(',
idExprNode,
')',
])));
}
else {
// 传递已绑定的 style
styleProp.exp = (0, compiler_core_1.createCompoundExpression)([
context.helperString(runtimeHelpers_1.SET_UNI_ELEMENT_STYLE) + '(',
idExprNode,
',',
styleProp.exp,
')',
]);
}
}
}
exports.rewriteId = rewriteId;
function parseUniElementRefCode(node, context) {
const refProp = (0, compiler_core_1.findProp)(node, utils_1.ATTR_VUE_REF) || (0, compiler_core_1.findProp)(node, 'ref');
if (!refProp) {
return '';
}
const { code, refKey } = (0, transformRef_1.parseRefCode)(refProp, context);
const opts = {};
if (refKey) {
opts.k = refKey;
}
if (context.inVFor) {
opts.f = 1;
}
const children = [',', code];
if (Object.keys(opts).length) {
children.push(',', JSON.stringify(opts));
}
return (0, compiler_core_1.createCompoundExpression)(children);
}