1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const t = require("babel-types");
|
4 | const utils_1 = require("./utils");
|
5 | const jsx_1 = require("./jsx");
|
6 | const lodash_1 = require("lodash");
|
7 | const renderPropsMap = new Map();
|
8 | const RENDER_PROPS_EVENTS = '$$renderPropsEvents';
|
9 | function injectRenderPropsListener(attrPath, attrName, attrExpr, componentName) {
|
10 | const randomLetters = utils_1.createRandomLetters(5);
|
11 | const renderClosureFuncName = attrName + randomLetters;
|
12 | const jsxDecl = utils_1.buildConstVariableDeclaration(renderClosureFuncName, attrExpr);
|
13 | const block = jsx_1.buildBlockElement([], true);
|
14 | const renderPropsArgs = t.memberExpression(t.thisExpression(), t.identifier(renderClosureFuncName));
|
15 | renderPropsMap.set(componentName + '_' + attrName, renderClosureFuncName);
|
16 | block.children = [
|
17 | t.jSXExpressionContainer(t.callExpression(t.identifier(renderClosureFuncName), [renderPropsArgs]))
|
18 | ];
|
19 | const listener = buildListener(renderClosureFuncName, renderPropsArgs);
|
20 | const stemParent = attrPath.getStatementParent();
|
21 | stemParent.insertBefore(listener);
|
22 | stemParent.insertBefore(jsxDecl);
|
23 | attrPath.get('value').replaceWith(t.jSXExpressionContainer(block));
|
24 | setRenderPropsEvents(attrPath, renderClosureFuncName);
|
25 | }
|
26 | exports.injectRenderPropsListener = injectRenderPropsListener;
|
27 | function setRenderPropsEvents(attrPath, renderClosureFuncName) {
|
28 | const classDecl = attrPath.findParent(p => p.isClassDeclaration());
|
29 | if (classDecl && classDecl.isClassDeclaration()) {
|
30 | let hasEvent = false;
|
31 | for (const s of classDecl.node.body.body) {
|
32 | if (t.isClassProperty(s) && s.key.name === RENDER_PROPS_EVENTS && t.isArrayExpression(s.value)) {
|
33 | hasEvent = true;
|
34 | if (s.value.elements.some(e => t.isStringLiteral(e) && e.value === renderClosureFuncName)) {
|
35 | break;
|
36 | }
|
37 | s.value.elements.push(t.stringLiteral(renderClosureFuncName));
|
38 | }
|
39 | }
|
40 | if (!hasEvent) {
|
41 | classDecl.node.body.body.push(t.classProperty(t.identifier(RENDER_PROPS_EVENTS), t.arrayExpression([t.stringLiteral(renderClosureFuncName)])));
|
42 | }
|
43 | }
|
44 | }
|
45 | function injectRenderPropsEmiter(callExpr, attrName) {
|
46 | const classDecl = callExpr.findParent(p => p.isClassDeclaration());
|
47 | const classDeclName = classDecl && classDecl.isClassDeclaration() && lodash_1.get(classDecl, 'node.id.name', '');
|
48 | if (typeof classDeclName !== 'string') {
|
49 | throw utils_1.codeFrameError(classDecl, '使用 render props 必须指定 class 的名称。');
|
50 | }
|
51 | const renderClosureFuncName = renderPropsMap.get(classDeclName + '_' + attrName) || '';
|
52 | const args = [t.stringLiteral(renderClosureFuncName)];
|
53 | if (Array.isArray(callExpr.node.arguments) && callExpr.node.arguments.length) {
|
54 | args.push(callExpr.node.arguments[0]);
|
55 | }
|
56 | const emitter = t.callExpression(t.memberExpression(buildEventCenterMemberExpr(), t.identifier('trigger')), args);
|
57 | const stemParent = callExpr.getStatementParent();
|
58 | stemParent.insertBefore(t.expressionStatement(emitter));
|
59 | }
|
60 | exports.injectRenderPropsEmiter = injectRenderPropsEmiter;
|
61 | function buildListener(renderClosureFuncName, renderPropsArgs) {
|
62 | return t.expressionStatement(t.callExpression(t.memberExpression(buildEventCenterMemberExpr(), t.identifier('on')), [t.stringLiteral(renderClosureFuncName), t.arrowFunctionExpression([t.identifier('e')], t.blockStatement([
|
63 | t.ifStatement(t.unaryExpression('!', t.callExpression(t.memberExpression(t.identifier('Taro'), t.identifier('shallowEqual')), [t.identifier('e'), renderPropsArgs])), t.blockStatement([
|
64 | t.expressionStatement(t.assignmentExpression('=', renderPropsArgs, t.identifier('e'))),
|
65 | t.expressionStatement(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier('setState')), [t.objectExpression([])]))
|
66 | ]))
|
67 | ]))]));
|
68 | }
|
69 | function buildEventCenterMemberExpr() {
|
70 | return t.memberExpression(t.identifier('Taro'), t.identifier('eventCenter'));
|
71 | }
|
72 |
|
\ | No newline at end of file |