Skip to content

Commit 3814c31

Browse files
committed
feat(transformer): 支持在 JSX 使用 this.xxx 直接访问 this.xxx 的值
1 parent 0cf7da9 commit 3814c31

File tree

1 file changed

+84
-41
lines changed

1 file changed

+84
-41
lines changed

packages/taro-transformer-wx/src/render.ts

Lines changed: 84 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ export class RenderParser {
111111
private usedEvents = new Set<string>()
112112
private customComponentNames: Set<string>
113113
private loopCalleeId = new Set<t.Identifier>()
114+
private usedThisProperties = new Set<t.Identifier>()
114115

115116
private renderPath: NodePath<t.ClassMethod>
116117
private methods: ClassMethodsMap
@@ -737,48 +738,78 @@ export class RenderParser {
737738
this.addRefIdentifier(path, path.node)
738739
}
739740
},
740-
MemberExpression: (path) => {
741-
if (!isChildrenOfJSXAttr(path)) {
742-
return
743-
}
744-
if (!path.isReferencedMemberExpression() || path.parentPath.isMemberExpression()) {
745-
return
746-
}
747-
const { object, property } = path.node
748-
if (
749-
t.isMemberExpression(object) &&
750-
t.isThisExpression(object.object) &&
751-
t.isIdentifier(object.property, { name: 'state' })
752-
) {
753-
if (t.isIdentifier(property)) {
754-
this.usedThisState.add(property.name)
755-
} else if (t.isMemberExpression(property)) {
756-
const id = findFirstIdentifierFromMemberExpression(property)
757-
if (id && this.renderScope.hasBinding(id.name)) {
758-
this.usedThisState.add(id.name)
741+
MemberExpression: {
742+
exit: (path: NodePath<t.MemberExpression>) => {
743+
const { object, property } = path.node
744+
if (!path.isReferencedMemberExpression()) {
745+
return
746+
}
747+
if (!t.isThisExpression(object)) {
748+
return
749+
}
750+
const reserves = new Set([
751+
'state',
752+
'props',
753+
...this.methods.keys()
754+
])
755+
if (t.isIdentifier(property) || t.isMemberExpression(property)) {
756+
const id = t.isIdentifier(property) ? property : findFirstIdentifierFromMemberExpression(property)
757+
if (reserves.has(id.name)) {
758+
return
759+
}
760+
const jsxAttr = path.findParent(p => p.isJSXAttribute()) as NodePath<t.JSXAttribute>
761+
if (jsxAttr && t.isJSXIdentifier(jsxAttr.node.name) && jsxAttr.node.name.name.startsWith('on')) {
762+
return
763+
}
764+
if (t.isIdentifier(id)) {
765+
this.referencedIdentifiers.add(id)
766+
this.usedThisProperties.add(id)
759767
}
760768
}
761-
return
762-
}
763-
const code = generate(path.node).code
764-
if (code.includes('this.$router.params') && t.isIdentifier(property)) {
765-
const name = this.renderScope.generateUid(property.name)
766-
const dcl = buildConstVariableDeclaration(name, path.node)
767-
this.renderPath.node.body.body.unshift(dcl)
768-
path.replaceWith(t.identifier(name))
769-
}
770-
const parentPath = path.parentPath
771-
const id = findFirstIdentifierFromMemberExpression(path.node)
772-
if (t.isThisExpression(id)) {
773-
return
774-
}
775-
if (
776-
parentPath.isConditionalExpression() ||
777-
parentPath.isLogicalExpression() ||
778-
parentPath.isJSXExpressionContainer() ||
779-
(this.renderScope.hasOwnBinding(id.name))
780-
) {
781-
this.addRefIdentifier(path, id)
769+
},
770+
enter: (path) => {
771+
if (!isChildrenOfJSXAttr(path)) {
772+
return
773+
}
774+
if (!path.isReferencedMemberExpression() || path.parentPath.isMemberExpression()) {
775+
return
776+
}
777+
const { object, property } = path.node
778+
if (
779+
t.isMemberExpression(object) &&
780+
t.isThisExpression(object.object) &&
781+
t.isIdentifier(object.property, { name: 'state' })
782+
) {
783+
if (t.isIdentifier(property)) {
784+
this.usedThisState.add(property.name)
785+
} else if (t.isMemberExpression(property)) {
786+
const id = findFirstIdentifierFromMemberExpression(property)
787+
if (id && this.renderScope.hasBinding(id.name)) {
788+
this.usedThisState.add(id.name)
789+
}
790+
}
791+
return
792+
}
793+
const code = generate(path.node).code
794+
if (code.includes('this.$router.params') && t.isIdentifier(property)) {
795+
const name = this.renderScope.generateUid(property.name)
796+
const dcl = buildConstVariableDeclaration(name, path.node)
797+
this.renderPath.node.body.body.unshift(dcl)
798+
path.replaceWith(t.identifier(name))
799+
}
800+
const parentPath = path.parentPath
801+
const id = findFirstIdentifierFromMemberExpression(path.node)
802+
if (t.isThisExpression(id)) {
803+
return
804+
}
805+
if (
806+
parentPath.isConditionalExpression() ||
807+
parentPath.isLogicalExpression() ||
808+
parentPath.isJSXExpressionContainer() ||
809+
(this.renderScope.hasOwnBinding(id.name))
810+
) {
811+
this.addRefIdentifier(path, id)
812+
}
782813
}
783814
},
784815
ArrowFunctionExpression: (path) => {
@@ -1256,7 +1287,19 @@ export class RenderParser {
12561287

12571288
this.renderPath.node.body.body.unshift(
12581289
template(`this.__state = arguments[0] || this.state || {};`)(),
1259-
template(`this.__props = arguments[1] || this.props || {};`)()
1290+
template(`this.__props = arguments[1] || this.props || {};`)(),
1291+
t.variableDeclaration(
1292+
'const',
1293+
[
1294+
t.variableDeclarator(
1295+
t.objectPattern(Array.from(this.usedThisProperties).map(p => t.objectProperty(
1296+
t.identifier(p.name),
1297+
t.identifier(p.name)
1298+
) as any)),
1299+
t.thisExpression()
1300+
)
1301+
]
1302+
)
12601303
)
12611304

12621305
if (t.isIdentifier(this.renderPath.node.key)) {

0 commit comments

Comments
 (0)