Skip to content

babel 插件

vIfTransformPlugin

  • 让 react 的 v-if 语法支持在 jsx 中使用

插件实现

js
// plugins/vIfTransformPlugin.js
import { types } from "@babel/core";

function vIfTransformPlugin() {
  return {
    visitor: {
      JSXElement(path) {
        const { node } = path;
        const { openingElement } = node;
        const { attributes } = openingElement;

        const attrIndex = attributes.findIndex(
          (attr) => attr.name?.name === "v-if"
        );

        if (attrIndex === -1) return;

        // 获取条件表达式
        const condition = attributes[attrIndex].value?.expression;

        // 移除属性
        attributes.splice(attrIndex, 1);

        // 替换为条件渲染:{condition && <div />}
        path.replaceWith(
          types.jsxExpressionContainer(
            types.logicalExpression("&&", condition, node)
          )
        );
      },
    },
  };
}

export default vIfTransformPlugin;

引用插件

js
// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import vIfElsePlugin from "./plugins/vIfTransformPlugin";

export default defineConfig({
  plugins: [
    react({
      babel: {
        plugins: [vIfElsePlugin], // 应用自定义 Babel 插件
      },
    }),
  ],
});

使用

jsx
import { useState } from "react";

function App() {
  let [num, setNum] = useState(0);
  return (
    <>
      <button onClick={() => setNum((num) => ++num)}>click{num}</button>
      <div v-if={num == 0}>aa{num}</div>
      <div v-if={num == 1}>bb{num}</div>
      <div v-if={num >= 2}>cc{num}</div>
    </>
  );
}

export default App;