在构建Mitosis组件时,您可能有时会有独特和特殊的需求。如果您想要根据自己的需求转换Mitosis生成的输出,比如:

在每个Mitosis文件的顶部添加特殊的导入语句 为一个给定目标删除特定的样式属性(例如,如果您希望您的react-native输出忽略特定的样式属性,而其他地方依赖该属性。) 仅修改某些组件以进行动态导入 这(以及更多)都是可能的,这要归功于Mitosis强大的插件系统。

插件

在目录的mitosis.config.js中,您可以为每个代码生成器提供一个插件数组。您可以使用许多不同类型的插件:

  1. export type Plugin = {
  2. json?: {
  3. // 在任何修改器之前执行
  4. pre?: (json: MitosisComponent) => MitosisComponent | void;
  5. // 在内置修改器之后执行
  6. post?: (json: MitosisComponent) => MitosisComponent | void;
  7. };
  8. code?: {
  9. // 在格式化之前执行
  10. pre?: (code: string) => string;
  11. // 在格式化之后执行
  12. post?: (code: string) => string;
  13. };
  14. };

我们在四个不同的点上运行插件:

  • preJSON:在对Mitosis JSON运行任何默认修改器之前
  • postJSON:在对Mitosis JSON运行所有内置修改器之后
  • preCode:在对Mitosis输出运行任何格式化之前(我们使用prettier进行格式化)
  • postCode:在对Mitosis输出运行任何格式化之后(我们使用prettier进行格式化)

JSON插件接收Mitosis组件的完整JSON对象作为参数。同样,代码插件接收代码字符串。

我们甚至在内部使用插件来生成Mitosis组件!以下是我们的react-native插件的示例:

  1. // mitosis/packages/core/src/generators/react-native.ts
  2. // 将DOM标签转换为<View />和<Text />的插件
  3. function processReactNative() {
  4. return () => ({
  5. json: {
  6. pre: (json: MitosisComponent) => {
  7. traverse(json).forEach((node) => {
  8. if (isMitosisNode(node)) {
  9. // TODO: 处理TextInput、Image等
  10. if (node.name.toLowerCase() === node.name) {
  11. node.name = 'View';
  12. }
  13. if (
  14. node.properties._text?.trim().length ||
  15. node.bindings._text?.trim()?.length
  16. ) {
  17. node.name = 'Text';
  18. }
  19. if (node.properties.class) {
  20. delete node.properties.class;
  21. }
  22. if (node.properties.className) {
  23. delete node.properties.className;
  24. }
  25. if (node.bindings.class) {
  26. delete node.bindings.class;
  27. }
  28. if (node.bindings.className) {
  29. delete node.bindings.className;
  30. }
  31. }
  32. });
  33. },
  34. },
  35. });
  36. }

您会看到我们遍历JSON节点,对于每个MitosisNode,我们删除class和className值和绑定。这是因为React-Native在移动端不支持类名。

useMetadata 如果您想要插件仅应用于特定的一组组件,或者如果您想要为插件提供一些元数据,该元数据将取决于正在编译的组件,则我们的useMetadata挂钩就非常有用。您只需要导入并使用该挂钩(您可以在mitosis组件文件的任何地方使用它,甚至在顶级根级别!):

  1. import { useMetadata } from '@builder.io/mitosis';
  2. useMetadata({ mySpecialComponentType: 'ABC' });
  3. export default function SmileReviews(props: SmileReviewsProps) {
  4. return <div>{/**/}</div>;
  5. }

元数据将存储在Mitosis组件的JSON中,位于json.meta.useMetadata.mySpecialComponentType下。然后,您可以在JSON pre/post插件中使用它:

  1. const plugin = {
  2. json: {
  3. pre: (json: MitosisComponent) => {
  4. const myComponentType = json.meta.useMetadata?.mySpecialComponentType;
  5. if (myComponentType === 'ABC') {
  6. //...
  7. }
  8. },
  9. },
  10. };

组件JSON

Mitosis引擎的工作方式是:

  • 您编写一个.lite.jsx组件
  • Mitosis JSX解析器将其转换为MitosisComponent JSON
  • 该JSON被提供给您选择的生成器,生成器将其提供给插件。 有关JSON包含的详细信息,请查看已记录的类型:

  • MitosisComponent

  • MitosisNode:每个MitosisComponent都将在component.children下具有多个MitosisNode。每个节点表示一个DOM/JSX节点