Skip to content

支持替换 jsx 中的属性名 #2077

@fjc0k

Description

@fjc0k

譬如

输入:

<MyView customClass='red'>hello</MyView>

输出:

<MyView custom-class='red'>hello</MyView>

由来

在微信小程序的样式体系里,addGlobalClass 只能对应用级别(app.wxss)和页面级别(page.wxss)里的类名生效,而如果是组件级别(component.wxss)里的类名,则需要利用 externalClasses。即一个组件如果不是被一个页面引用,而是被另一个组件引用,只能使用 externalClasses 修改内部样式。

同时,externalClasses 的设计上又有一个神秘的限制,不能使用驼峰命名,于是我们在使用时就必须得容忍这样的代码:

<MyView custom-class='red'>hello</MyView>

而如果你又在使用 TypeScript,因为带 - 的标识符被认为非法,你将得不到任何提示,就算你的 MyView 如此定义:

class MyView extends Taro.Component<{ 'custom-class': string }> {}

想法

因此,我觉得可以通过 babel 将 customClass 转换为 custom-class,如此既符合小程序的规范,也符合 jsx 的书写习惯。

个人看法,可以在 config/index.js 暴露一个选项,比如 jsxAttributeNameReplace

{
  jsxAttributeNameReplace: {
    customClass: 'custom-class',
    customTitleClass: 'custom-title-class',
  }
}

最后

下面是我的测试代码,是可行的,期望实现,谢谢。

import * as babel from 'babel-core'
import * as t from 'babel-types'

const code = `
  const x = 1;
  const y = x === 2;
  const z = x === 3;
  const jsx = <div customName='red'>x</div>;
`.replace(/^ {2}/g, '').trim()

const result = babel.transform(code, {
  plugins: [
    ((): babel.PluginObj => ({
      // @ts-ignore
      inherits: require("babel-plugin-syntax-jsx"),
      visitor: {
        JSXAttribute(path) {
          if (path.get('name').isJSXIdentifier({ name: 'customName' })) {
            path.node.name = t.jSXIdentifier('custom-class')
          }
        }
      }
    }))
  ]
})

console.log('============\n')
console.log(result.code)
console.log('\n============')

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions