vModel.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.transformModel = void 0;
  4. const shared_1 = require("@vue/shared");
  5. const compiler_core_1 = require("@vue/compiler-core");
  6. const compiler_dom_1 = require("@vue/compiler-dom");
  7. const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
  8. const runtimeHelpers_1 = require("../runtimeHelpers");
  9. const codegen_1 = require("../codegen");
  10. const vOn_1 = require("./vOn");
  11. const transformModel = (dir, node, _context) => {
  12. const context = _context;
  13. const baseResult = (0, compiler_core_1.transformModel)(dir, node, _context);
  14. // base transform has errors OR component v-model (only need props)
  15. if (!baseResult.props.length || node.tagType === 1 /* ElementTypes.COMPONENT */) {
  16. return transformComponentVModel(baseResult.props, node, context);
  17. }
  18. if (dir.arg) {
  19. context.onError((0, compiler_dom_1.createDOMCompilerError)(58 /* DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT */, dir.arg.loc));
  20. }
  21. function checkDuplicatedValue() {
  22. const value = (0, compiler_core_1.findProp)(node, 'value');
  23. if (value) {
  24. context.onError((0, compiler_dom_1.createDOMCompilerError)(60 /* DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE */, value.loc));
  25. }
  26. }
  27. const { tag } = node;
  28. if (tag === 'input' || tag === 'textarea') {
  29. checkDuplicatedValue();
  30. }
  31. else {
  32. context.onError((0, compiler_dom_1.createDOMCompilerError)(57 /* DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT */, dir.loc));
  33. }
  34. if (dir.modifiers.length) {
  35. const arg = dir.arg;
  36. const modifiers = dir.modifiers
  37. .map((m) => ((0, compiler_core_1.isSimpleIdentifier)(m) ? m : JSON.stringify(m)) + `: true`)
  38. .join(`, `);
  39. const modifiersKey = arg
  40. ? (0, compiler_core_1.isStaticExp)(arg)
  41. ? `${arg.content}Modifiers`
  42. : (0, compiler_core_1.createCompoundExpression)([arg, ' + "Modifiers"'])
  43. : `modelModifiers`;
  44. baseResult.props.push((0, compiler_core_1.createObjectProperty)(modifiersKey, (0, compiler_core_1.createSimpleExpression)(`{ ${modifiers} }`, false, dir.loc, 2 /* ConstantTypes.CAN_HOIST */)));
  45. }
  46. return transformElementVModel(baseResult.props, node, context);
  47. };
  48. exports.transformModel = transformModel;
  49. function findInputDirectiveNode(props) {
  50. return props.find((prop) => prop.type === 7 /* NodeTypes.DIRECTIVE */ &&
  51. prop.name === 'on' &&
  52. prop.arg?.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ &&
  53. prop.arg.content === 'input');
  54. }
  55. function transformElementVModel(props, node, context) {
  56. const dirs = transformVModel(props, node, context, {
  57. isComponent: false,
  58. binding: 'value',
  59. event: 'input',
  60. formatEventCode(code) {
  61. return code.replace(/=\s\$event/g, `= $event.detail.value`);
  62. },
  63. });
  64. if (dirs.length === 2) {
  65. // 快手小程序的 input v-model 被转换到 data-e-o 中,补充到 data-e-o 中
  66. const inputExp = findDatasetEventOpts(node);
  67. if (inputExp) {
  68. inputExp.children[2] = combineVOn(dirs[1].exp, inputExp.children[2], node, context);
  69. dirs.length = 1;
  70. }
  71. else {
  72. const inputDir = findInputDirectiveNode(node.props);
  73. if (inputDir && inputDir.exp) {
  74. // 合并到已有的 input 事件中
  75. inputDir.exp = combineVOn(dirs[1].exp, inputDir.exp, node, context);
  76. dirs.length = 1;
  77. }
  78. }
  79. }
  80. return { props: dirs };
  81. }
  82. /**
  83. * {
  84. * "type": 7,
  85. * "name": "bind",
  86. * "loc": {},
  87. * "modifiers": [],
  88. * "arg": {
  89. * "type": 4,
  90. * "loc": {},
  91. * "content": "data-e-o",
  92. * "isStatic": true,
  93. * "constType": 3
  94. * },
  95. * "exp": {
  96. * "type": 8,
  97. * "loc": {},
  98. * "children": ["{", {
  99. * "type": 8,
  100. * "loc": {},
  101. * "children": ["'input'", ": ", {
  102. * "type": 8,
  103. * "loc": {},
  104. * "children": ["_o(", {
  105. * "type": 4,
  106. * "content": "_ctx.input",
  107. * "isStatic": false,
  108. * "constType": 0,
  109. * "loc": {}
  110. * }, ")"]
  111. * }, ","]
  112. * }, "}"]
  113. * }
  114. * }
  115. * @param node
  116. * @returns
  117. */
  118. function findDatasetEventOpts(node) {
  119. const eventOptsProp = (0, compiler_core_1.findProp)(node, uni_cli_shared_1.ATTR_DATASET_EVENT_OPTS, true, false);
  120. if (!eventOptsProp) {
  121. return;
  122. }
  123. const { exp } = eventOptsProp;
  124. if (exp?.type !== 8 /* NodeTypes.COMPOUND_EXPRESSION */) {
  125. return;
  126. }
  127. for (let i = 0; i < exp.children.length; i++) {
  128. const childExp = exp.children[i];
  129. if ((0, shared_1.isSymbol)(childExp) || (0, shared_1.isString)(childExp)) {
  130. continue;
  131. }
  132. if (childExp.type !== 8 /* NodeTypes.COMPOUND_EXPRESSION */) {
  133. continue;
  134. }
  135. if (childExp.children[0] !== `'input'`) {
  136. continue;
  137. }
  138. const inputExp = childExp.children[2];
  139. if ((0, shared_1.isSymbol)(inputExp) ||
  140. (0, shared_1.isString)(inputExp) ||
  141. inputExp.type !== 8 /* NodeTypes.COMPOUND_EXPRESSION */) {
  142. continue;
  143. }
  144. return childExp;
  145. }
  146. }
  147. function parseVOn(exp, context) {
  148. return (0, codegen_1.genExpr)(exp).slice(context.helperString(runtimeHelpers_1.V_ON).length + 1, -1);
  149. }
  150. function combineVOn(exp1, exp2, node, context) {
  151. return (0, vOn_1.wrapperVOn)((0, compiler_core_1.createCompoundExpression)([
  152. `[`,
  153. parseVOn(exp1, context),
  154. ',',
  155. parseVOn(exp2, context),
  156. `]`,
  157. ]), node, context);
  158. }
  159. function transformComponentVModel(props, node, context) {
  160. return {
  161. props: transformVModel(props, node, context, {
  162. isComponent: true,
  163. formatEventCode(code) {
  164. return code;
  165. },
  166. }),
  167. };
  168. }
  169. function transformVModel(props, node, context, { isComponent, binding, event, formatEventCode, }) {
  170. if (props.length < 2) {
  171. return [];
  172. }
  173. const { key: modelValueArg, value: modelValeExpr } = props[0];
  174. const { key: onUpdateArg, value: onUpdateExpr } = props[1];
  175. if (modelValueArg.type !== 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
  176. return [];
  177. }
  178. if (onUpdateArg.type !== 4 /* NodeTypes.SIMPLE_EXPRESSION */ ||
  179. !onUpdateArg.content.startsWith('onUpdate:')) {
  180. return [];
  181. }
  182. const vBindModelValue = (0, uni_cli_shared_1.createBindDirectiveNode)(binding || modelValueArg.content, (0, codegen_1.genExpr)(modelValeExpr));
  183. const modifiers = parseVModelModifiers(props[2]);
  184. // onUpdateExpr 通常是 ExpressionNode 或者被 cache 的 ExpressionNode
  185. const vOnValue = (onUpdateExpr.type === 20 /* NodeTypes.JS_CACHE_EXPRESSION */
  186. ? onUpdateExpr.value
  187. : onUpdateExpr);
  188. 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
  189. ? wrapperVModelModifiers(vOnValue, modifiers, context, isComponent)
  190. : vOnValue, node, context))));
  191. return [vBindModelValue, vOnUpdate];
  192. }
  193. function parseVModelModifiers(property) {
  194. if (property &&
  195. (0, uni_cli_shared_1.isSimpleExpressionNode)(property.key) &&
  196. property.key.content.endsWith('Modifiers') &&
  197. (0, uni_cli_shared_1.isSimpleExpressionNode)(property.value)) {
  198. return property.value.content;
  199. }
  200. }
  201. function wrapperVModelModifiers(exp, modifiers, context, isComponent = false) {
  202. return (0, compiler_core_1.createCompoundExpression)([
  203. `${context.helperString(runtimeHelpers_1.WITH_MODEL_MODIFIERS)}(`,
  204. exp,
  205. ',',
  206. modifiers,
  207. `${isComponent ? `, true` : ``}`,
  208. `)`,
  209. ]);
  210. }