transformSlot.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.rewriteSlot = void 0;
  4. const compiler_core_1 = require("@vue/compiler-core");
  5. const shared_1 = require("@vue/shared");
  6. const uni_shared_1 = require("@dcloudio/uni-shared");
  7. const runtimeHelpers_1 = require("../runtimeHelpers");
  8. const codegen_1 = require("../codegen");
  9. const transform_1 = require("../transform");
  10. const transformElement_1 = require("./transformElement");
  11. const utils_1 = require("./utils");
  12. const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
  13. const __1 = require("..");
  14. const ast_1 = require("../ast");
  15. function rewriteSlot(node, context) {
  16. let slotName = `"${uni_shared_1.SLOT_DEFAULT_NAME}"`;
  17. let hasOtherDir = false;
  18. const nonNameProps = [];
  19. const { props } = node;
  20. // 默认插槽强制设置name
  21. if (!(0, compiler_core_1.findProp)(node, 'name')) {
  22. props.unshift((0, uni_cli_shared_1.createAttributeNode)('name', 'default'));
  23. }
  24. for (let i = 0; i < props.length; i++) {
  25. const p = props[i];
  26. if (p.type === 6 /* NodeTypes.ATTRIBUTE */) {
  27. if (p.value) {
  28. if (p.name === 'name') {
  29. p.value.content = (0, uni_shared_1.dynamicSlotName)(p.value.content);
  30. slotName = JSON.stringify(p.value.content);
  31. }
  32. else {
  33. p.name = (0, shared_1.camelize)(p.name);
  34. nonNameProps.push(p);
  35. }
  36. }
  37. }
  38. else {
  39. if (p.name !== 'bind') {
  40. hasOtherDir = true;
  41. }
  42. if (p.name === 'bind' && (0, compiler_core_1.isStaticArgOf)(p.arg, 'name')) {
  43. if (p.exp) {
  44. slotName = (0, compiler_core_1.createCompoundExpression)([
  45. context.helperString(__1.DYNAMIC_SLOT) + '(',
  46. p.exp,
  47. ')',
  48. ]);
  49. let slotKey;
  50. const keys = parseVForKeyAlias(context);
  51. if (keys.length) {
  52. const babelNode = (0, ast_1.parseExpr)(p.exp, context);
  53. // 在 v-for 中,判断是否插槽名使用 v-for 的 key 变量
  54. if (babelNode && (0, utils_1.isReferencedByIds)(babelNode, keys)) {
  55. slotKey = parseScopedSlotKey(context);
  56. }
  57. }
  58. p.exp = (0, utils_1.rewriteExpression)((0, compiler_core_1.createCompoundExpression)([
  59. context.helperString(__1.DYNAMIC_SLOT) + '(',
  60. p.exp,
  61. slotKey ? `+'-'+` + slotKey : '',
  62. ')',
  63. ]), context);
  64. }
  65. }
  66. else {
  67. if (p.name === 'bind' && p.arg && (0, compiler_core_1.isStaticExp)(p.arg)) {
  68. p.arg.content = (0, shared_1.camelize)(p.arg.content);
  69. }
  70. nonNameProps.push(p);
  71. }
  72. }
  73. }
  74. if (hasOtherDir) {
  75. context.onError((0, compiler_core_1.createCompilerError)(36 /* ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET */, node.loc));
  76. }
  77. if (nonNameProps.length > 0) {
  78. (0, transformElement_1.processProps)(node, context, nonNameProps);
  79. const properties = [];
  80. nonNameProps.forEach((prop) => {
  81. const property = transformProperty(prop, context);
  82. property && properties.push(property);
  83. });
  84. if (properties.length) {
  85. transformScopedSlotName(node, context);
  86. const vForIndexAlias = parseVForIndexAlias(context);
  87. (0, utils_1.rewriteExpression)((0, compiler_core_1.createCompoundExpression)([
  88. context.helperString(runtimeHelpers_1.RENDER_SLOT) + '(',
  89. slotName,
  90. ',',
  91. `{${properties.join(',')}}`,
  92. `${vForIndexAlias ? ',' + parseScopedSlotKey(context) : ''}`,
  93. ')',
  94. ]), context);
  95. }
  96. else {
  97. // 非作用域默认插槽直接移除命名
  98. if (slotName === `"${uni_shared_1.SLOT_DEFAULT_NAME}"`) {
  99. (0, utils_1.removeAttribute)(node, 'name');
  100. }
  101. }
  102. }
  103. else {
  104. // 非作用域默认插槽直接移除命名
  105. if (slotName === `"${uni_shared_1.SLOT_DEFAULT_NAME}"`) {
  106. (0, utils_1.removeAttribute)(node, 'name');
  107. }
  108. }
  109. }
  110. exports.rewriteSlot = rewriteSlot;
  111. function parseVForIndexAlias(context) {
  112. let { currentScope } = context;
  113. while (currentScope) {
  114. if ((0, transform_1.isVForScope)(currentScope) && !(0, transform_1.isScopedSlotVFor)(currentScope)) {
  115. return currentScope.indexAlias;
  116. }
  117. currentScope = currentScope.parent;
  118. }
  119. }
  120. function transformScopedSlotName(node, context) {
  121. if (!context.miniProgram.slot.dynamicSlotNames) {
  122. return;
  123. }
  124. const slotKey = parseScopedSlotKey(context);
  125. if (!slotKey) {
  126. return;
  127. }
  128. const nameProps = (0, compiler_core_1.findProp)(node, 'name');
  129. if (nameProps && nameProps.type === 6 /* NodeTypes.ATTRIBUTE */ && nameProps.value) {
  130. const { props } = node;
  131. props.splice(props.indexOf(nameProps), 1, createScopedSlotDirectiveNode(nameProps.value.content, slotKey, context));
  132. }
  133. }
  134. function createScopedSlotDirectiveNode(name, slotKey, context) {
  135. const dir = (0, uni_cli_shared_1.createBindDirectiveNode)('name', (0, utils_1.rewriteExpression)((0, compiler_core_1.createSimpleExpression)(`"${name}-"+` + slotKey), context)
  136. .content);
  137. // 存储原始的 slot 名称
  138. dir.slotName = name;
  139. return dir;
  140. }
  141. function parseVForKeyAlias(context) {
  142. let { currentScope } = context;
  143. const keys = [];
  144. while (currentScope) {
  145. if ((0, transform_1.isVForScope)(currentScope) && !(0, transform_1.isScopedSlotVFor)(currentScope)) {
  146. keys.push(currentScope.keyAlias);
  147. }
  148. currentScope = currentScope.parent;
  149. }
  150. return keys;
  151. }
  152. function parseVForIndexes(context) {
  153. let { currentScope } = context;
  154. const indexes = [];
  155. while (currentScope) {
  156. if ((0, transform_1.isVForScope)(currentScope) && !(0, transform_1.isScopedSlotVFor)(currentScope)) {
  157. indexes.push(currentScope.indexAlias);
  158. }
  159. currentScope = currentScope.parent;
  160. }
  161. return indexes;
  162. }
  163. function parseSlotKeyByVForIndexes(indexes) {
  164. return indexes.reverse().join(`+'-'+`);
  165. }
  166. function parseScopedSlotKey(context) {
  167. const indexes = parseVForIndexes(context);
  168. const inFor = !!indexes.length;
  169. if (inFor) {
  170. return parseSlotKeyByVForIndexes(indexes);
  171. }
  172. }
  173. function transformProperty(dir, _) {
  174. if ((0, uni_cli_shared_1.isDirectiveNode)(dir)) {
  175. if (!dir.arg || !dir.exp) {
  176. return;
  177. }
  178. const isStaticArg = dir.arg.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ && dir.arg.isStatic;
  179. if (isStaticArg) {
  180. return `${dir.arg.content}:${(0, codegen_1.genExpr)(dir.exp)}`;
  181. }
  182. return `[${(0, codegen_1.genExpr)(dir.arg)}||'']:${(0, codegen_1.genExpr)(dir.exp)}`;
  183. }
  184. if (dir.value) {
  185. return `${dir.name}:${(0, codegen_1.genExpr)(dir.value)}`;
  186. }
  187. }