211 lines
7.6 KiB
JavaScript
211 lines
7.6 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.transformModel = void 0;
|
|
const shared_1 = require("@vue/shared");
|
|
const compiler_core_1 = require("@vue/compiler-core");
|
|
const compiler_dom_1 = require("@vue/compiler-dom");
|
|
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
|
const runtimeHelpers_1 = require("../runtimeHelpers");
|
|
const codegen_1 = require("../codegen");
|
|
const vOn_1 = require("./vOn");
|
|
const transformModel = (dir, node, _context) => {
|
|
const context = _context;
|
|
const baseResult = (0, compiler_core_1.transformModel)(dir, node, _context);
|
|
// base transform has errors OR component v-model (only need props)
|
|
if (!baseResult.props.length || node.tagType === 1 /* ElementTypes.COMPONENT */) {
|
|
return transformComponentVModel(baseResult.props, node, context);
|
|
}
|
|
if (dir.arg) {
|
|
context.onError((0, compiler_dom_1.createDOMCompilerError)(56 /* DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT */, dir.arg.loc));
|
|
}
|
|
function checkDuplicatedValue() {
|
|
const value = (0, compiler_core_1.findProp)(node, 'value');
|
|
if (value) {
|
|
context.onError((0, compiler_dom_1.createDOMCompilerError)(58 /* DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE */, value.loc));
|
|
}
|
|
}
|
|
const { tag } = node;
|
|
if (tag === 'input' || tag === 'textarea') {
|
|
checkDuplicatedValue();
|
|
}
|
|
else {
|
|
context.onError((0, compiler_dom_1.createDOMCompilerError)(55 /* DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT */, dir.loc));
|
|
}
|
|
if (dir.modifiers.length) {
|
|
const arg = dir.arg;
|
|
const modifiers = dir.modifiers
|
|
.map((m) => ((0, compiler_core_1.isSimpleIdentifier)(m) ? m : JSON.stringify(m)) + `: true`)
|
|
.join(`, `);
|
|
const modifiersKey = arg
|
|
? (0, compiler_core_1.isStaticExp)(arg)
|
|
? `${arg.content}Modifiers`
|
|
: (0, compiler_core_1.createCompoundExpression)([arg, ' + "Modifiers"'])
|
|
: `modelModifiers`;
|
|
baseResult.props.push((0, compiler_core_1.createObjectProperty)(modifiersKey, (0, compiler_core_1.createSimpleExpression)(`{ ${modifiers} }`, false, dir.loc, 2 /* ConstantTypes.CAN_HOIST */)));
|
|
}
|
|
return transformElementVModel(baseResult.props, node, context);
|
|
};
|
|
exports.transformModel = transformModel;
|
|
function findInputDirectiveNode(props) {
|
|
return props.find((prop) => prop.type === 7 /* NodeTypes.DIRECTIVE */ &&
|
|
prop.name === 'on' &&
|
|
prop.arg?.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ &&
|
|
prop.arg.content === 'input');
|
|
}
|
|
function transformElementVModel(props, node, context) {
|
|
const dirs = transformVModel(props, node, context, {
|
|
isComponent: false,
|
|
binding: 'value',
|
|
event: 'input',
|
|
formatEventCode(code) {
|
|
return code.replace(/=\s\$event/g, `= $event.detail.value`);
|
|
},
|
|
});
|
|
if (dirs.length === 2) {
|
|
// 快手小程序的 input v-model 被转换到 data-e-o 中,补充到 data-e-o 中
|
|
const inputExp = findDatasetEventOpts(node);
|
|
if (inputExp) {
|
|
inputExp.children[2] = combineVOn(dirs[1].exp, inputExp.children[2], node, context);
|
|
dirs.length = 1;
|
|
}
|
|
else {
|
|
const inputDir = findInputDirectiveNode(node.props);
|
|
if (inputDir && inputDir.exp) {
|
|
// 合并到已有的 input 事件中
|
|
inputDir.exp = combineVOn(dirs[1].exp, inputDir.exp, node, context);
|
|
dirs.length = 1;
|
|
}
|
|
}
|
|
}
|
|
return { props: dirs };
|
|
}
|
|
/**
|
|
* {
|
|
* "type": 7,
|
|
* "name": "bind",
|
|
* "loc": {},
|
|
* "modifiers": [],
|
|
* "arg": {
|
|
* "type": 4,
|
|
* "loc": {},
|
|
* "content": "data-e-o",
|
|
* "isStatic": true,
|
|
* "constType": 3
|
|
* },
|
|
* "exp": {
|
|
* "type": 8,
|
|
* "loc": {},
|
|
* "children": ["{", {
|
|
* "type": 8,
|
|
* "loc": {},
|
|
* "children": ["'input'", ": ", {
|
|
* "type": 8,
|
|
* "loc": {},
|
|
* "children": ["_o(", {
|
|
* "type": 4,
|
|
* "content": "_ctx.input",
|
|
* "isStatic": false,
|
|
* "constType": 0,
|
|
* "loc": {}
|
|
* }, ")"]
|
|
* }, ","]
|
|
* }, "}"]
|
|
* }
|
|
* }
|
|
* @param node
|
|
* @returns
|
|
*/
|
|
function findDatasetEventOpts(node) {
|
|
const eventOptsProp = (0, compiler_core_1.findProp)(node, uni_cli_shared_1.ATTR_DATASET_EVENT_OPTS, true, false);
|
|
if (!eventOptsProp) {
|
|
return;
|
|
}
|
|
const { exp } = eventOptsProp;
|
|
if (exp?.type !== 8 /* NodeTypes.COMPOUND_EXPRESSION */) {
|
|
return;
|
|
}
|
|
for (let i = 0; i < exp.children.length; i++) {
|
|
const childExp = exp.children[i];
|
|
if ((0, shared_1.isSymbol)(childExp) || (0, shared_1.isString)(childExp)) {
|
|
continue;
|
|
}
|
|
if (childExp.type !== 8 /* NodeTypes.COMPOUND_EXPRESSION */) {
|
|
continue;
|
|
}
|
|
if (childExp.children[0] !== `'input'`) {
|
|
continue;
|
|
}
|
|
const inputExp = childExp.children[2];
|
|
if ((0, shared_1.isSymbol)(inputExp) ||
|
|
(0, shared_1.isString)(inputExp) ||
|
|
inputExp.type !== 8 /* NodeTypes.COMPOUND_EXPRESSION */) {
|
|
continue;
|
|
}
|
|
return childExp;
|
|
}
|
|
}
|
|
function parseVOn(exp, context) {
|
|
return (0, codegen_1.genExpr)(exp).slice(context.helperString(runtimeHelpers_1.V_ON).length + 1, -1);
|
|
}
|
|
function combineVOn(exp1, exp2, node, context) {
|
|
return (0, vOn_1.wrapperVOn)((0, compiler_core_1.createCompoundExpression)([
|
|
`[`,
|
|
parseVOn(exp1, context),
|
|
',',
|
|
parseVOn(exp2, context),
|
|
`]`,
|
|
]), node, context);
|
|
}
|
|
function transformComponentVModel(props, node, context) {
|
|
return {
|
|
props: transformVModel(props, node, context, {
|
|
isComponent: true,
|
|
formatEventCode(code) {
|
|
return code;
|
|
},
|
|
}),
|
|
};
|
|
}
|
|
function transformVModel(props, node, context, { isComponent, binding, event, formatEventCode, }) {
|
|
if (props.length < 2) {
|
|
return [];
|
|
}
|
|
const { key: modelValueArg, value: modelValeExpr } = props[0];
|
|
const { key: onUpdateArg, value: onUpdateExpr } = props[1];
|
|
if (modelValueArg.type !== 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
|
|
return [];
|
|
}
|
|
if (onUpdateArg.type !== 4 /* NodeTypes.SIMPLE_EXPRESSION */ ||
|
|
!onUpdateArg.content.startsWith('onUpdate:')) {
|
|
return [];
|
|
}
|
|
const vBindModelValue = (0, uni_cli_shared_1.createBindDirectiveNode)(binding || modelValueArg.content, (0, codegen_1.genExpr)(modelValeExpr));
|
|
const modifiers = parseVModelModifiers(props[2]);
|
|
// onUpdateExpr 通常是 ExpressionNode 或者被 cache 的 ExpressionNode
|
|
const vOnValue = (onUpdateExpr.type === 20 /* NodeTypes.JS_CACHE_EXPRESSION */
|
|
? onUpdateExpr.value
|
|
: onUpdateExpr);
|
|
const vOnUpdate = (0, uni_cli_shared_1.createOnDirectiveNode)(event || (0, shared_1.camelize)(onUpdateArg.content.replace('onUpdate:', 'update-')), formatEventCode((0, codegen_1.genExpr)((0, vOn_1.wrapperVOn)(modifiers
|
|
? wrapperVModelModifiers(vOnValue, modifiers, context, isComponent)
|
|
: vOnValue, node, context))));
|
|
return [vBindModelValue, vOnUpdate];
|
|
}
|
|
function parseVModelModifiers(property) {
|
|
if (property &&
|
|
(0, uni_cli_shared_1.isSimpleExpressionNode)(property.key) &&
|
|
property.key.content.endsWith('Modifiers') &&
|
|
(0, uni_cli_shared_1.isSimpleExpressionNode)(property.value)) {
|
|
return property.value.content;
|
|
}
|
|
}
|
|
function wrapperVModelModifiers(exp, modifiers, context, isComponent = false) {
|
|
return (0, compiler_core_1.createCompoundExpression)([
|
|
`${context.helperString(runtimeHelpers_1.WITH_MODEL_MODIFIERS)}(`,
|
|
exp,
|
|
',',
|
|
modifiers,
|
|
`${isComponent ? `, true` : ``}`,
|
|
`)`,
|
|
]);
|
|
}
|