发布于 2026-01-05 1 阅读
0

我开发了一个 VS Code 插件,可以在同一屏幕上的多个拆分编辑器中编写 React 组件的各个部分,即 JSX 分离函数组件。

我开发了一个 VS Code 插件,它可以在同一屏幕上的多个分屏编辑器中编写 React 组件的各个部分。

JSX 分离函数组件
Travis CI 状态 Codecov 执照

大家好!我是一名前端开发人员,使用 React 已经超过 6 年了,我比较喜欢 React 和 Vue 的组合React + Mobx + CSS-in-JS。我的大部分项目都是用 React 开发的,但也有少数项目使用了 Vue,而且我也在关注 Vue 的一些新特性。

最近,我发现了 Vue 生态系统的一个有趣的新功能:拆分编辑器

什么是拆分编辑器?

这是什么?这是名为VolarSplit Editors的全新 VS Code Vue 插件的一项功能,您可以安装 Volar并在 Vue 项目中体验它。以下是 Volar 的一个演示:

volar 演示

在演示中,点击Split Editors右上角的按钮,根据SFC 中的template/ style/script代码生成 3 个子编辑器,然后每个编辑器折叠不相关的代码。

起初,我只是觉得它很有趣。但经过思考和实验,我发现它也很有用。我的理解是:

它不仅使我们能够更加专注于开发每个组件中的某一类代码,而且还使我们能够轻松扫描和控制组件的整体代码,以处理不同类别代码之间的关系。

React 中拆分编辑器的可行性

因为我经常CSS in JS在 React 开发中编写样式,所以我想到了将这个想法与 React 结合起来的可行性。这个想法是,我们需要将 React 组件代码拆分成几个类别,放在同一个文件中,然后分别放入不同的拆分编辑器中,并将不相关的代码单独折叠起来。关于拆分形式,如果按照详细程度划分,可以分为以下几种情况:

一级

  • 组件代码
  • 样式代码

二级

如果划分更详细一些:

  • 组件逻辑代码
  • 组件渲染(JSX)代码
  • 样式代码

3级

事实上,还可以更详细一些:

  • 组件逻辑代码
  • 组件渲染(JSX)代码
  • 样式代码
  • 全局成员(常量、函数、自定义钩子等)

代码分类越细致,分屏编辑器的效果就越好。因为这样一来,每个编辑器就可以容纳更多不相关的代码,从而最大限度地减少垂直滚动的范围。

我的解决方法

目前,React 函数组件的语法非常自由。如果不引入任何代码结构规范,就很难完美地实现这个概念。这里,我将展示一个可行的解决方案,它可以实现上面提到的所有 1-3 级拆分形式。

实现这个想法应该不止一种方法。例如,我也在考虑基于常规函数组件语法的解决方案。但目前,本文中的方案已经能够完全实现拆分编辑器的理念。

这个解决方案需要在组件代码中添加一些约定,它使用了一个我最近开发的有趣的 React 函数组件 API:

GitHub 标志 joe-sky / jsx-sfc

类似 SFC 的 React 函数组件 API,用于管理 CSS-in-JS 和静态成员。

JSX 分离函数组件
Travis CI 状态 Codecov 执照

jsx-sfc 演示

介绍

jsx-sfcJSX Separate Function Components ( SFC ) 是一个类似 React 的函数组件 API,用于管理 CSS-in-JS 和静态成员。它使用 TypeScript 编写,具有完全的类型安全,并且基于编译器优化,因此也易于使用🧙🏼‍♂️。

在线演示在此CSS in JS使用twin.macro,可通过 Codesandbox体验类型提示/热重载/开发者工具)。

目前我正在计划开发 v2.0 版本,主要功能特性请点击此处查看。我会尽力减少破坏性改动。

特征

  • ✨在 React 函数组件中,清晰地分离JSX 标签逻辑样式以及任何其他成员。
  • 💫完全由 TypeScript实现的类型推断设计
  • 🎉 支持所有 React Hooks
  • 🔥 支持React 快速刷新
  • 🔧 支持 React ESLint 插件
  • 🔨 支持 React 开发工具
  • ⚡渲染性能与常规函数组件类似,存在……




此 APIjsx-sfc完全基于 TypeScript,它是一种与常规函数组件语法的 TS 类型一致的替代方案。它可以被视为一种思维模型,其代码结构类似于SFC,但它用于用纯 JSX/TSX 文件编写 React 函数组件。动态演示:

此外,jsx-sfc这是一个必须配合编译器使用的 API,才能提升其渲染性能和对 React 生态系统的适应性。我已经有超过 4 个生产项目在使用它。详情请参阅其文档

该 API 的 TS 类型定义(粗略版本):

function sfc<Props, ComponentData, Styles, Static>(
  options: {
    Component: (props?: Props & Styles & Static & { props: Props }) => ComponentData;
    render?: (args: { data: ComponentData; props: Props; styles: Styles } & Static) => JSX.Element;
    styles?: Styles;
    static?: Static;
  }
): React.FC<Props> & { Render: (data?: ComponentData), Component: React.FC<Props> } & Styles & Static;
Enter fullscreen mode Exit fullscreen mode

实际的类型定义在这里。

用于写入的组件jsx-sfc如下所示:

import sfc from 'jsx-sfc';
import styled from 'styled-components';

const Todo = sfc({
  Component({ value, styles: { Input } }) {
    return <Input value={value} />;
  },

  styles: () => ({
    Input: styled.input`
      color: #000;
    `
  })
});

/* Equivalent regular syntax:
function Todo({ value }) {
  return <Input value={value} />;
}

const Input = styled.input`
  color: #000;
`;

Object.assign(Todo, { styles: { Input } });
*/

const App = () => <Todo value="test" />;
Enter fullscreen mode Exit fullscreen mode

它还支持将组件的渲染部分编写在单独的函数中:

import sfc from 'jsx-sfc';
import styled from 'styled-components';

const Todo = sfc({
  Component() {
    const [value, setValue] = useState('test');

    return {
      value,
      onChange(e) {
        setValue(e.target.value);
      }
    };
  },

  render: ({ data, props, styles: { Input } }) => (
    return <Input defaultValue={props.value} value={data.value} onChange={data.onChange} />;
  ),

  styles: () => ({
    Input: styled.input`
      color: #000;
    `
  })
});

/* Equivalent regular syntax:
function Todo(props) {
  const [value, setValue] = useState('test');

  function onChange(e) {
    setValue(e.target.value);
  }

  return <Input defaultValue={props.value} value={value} onChange={onChange} />;
}

const Input = styled.input`
  color: #000;
`;

Object.assign(Todo, { styles: { Input } });
*/

const App = () => <Todo value="test" />;
Enter fullscreen mode Exit fullscreen mode

此外,它还支持定义组件的静态成员:

函数组件的静态成员是什么?您可以参考这里。

import sfc from 'jsx-sfc';
import styled from 'styled-components';

const Todo = sfc({
  Component({ hooks: { useInputValue } }) {
    const [value, setValue] = useInputValue('test');

    return {
      value,
      onChange(e) {
        setValue(e.target.value);
      }
    };
  },

  static: () => {
    function useInputValue(initial) {
      const [value, setValue] = useState(initial);
      return { value, setValue };
    }

    return {
      hooks: {
        useInputValue
      }
    };
  },

  render: ({ data, styles: { Input } }) => (
    return <Input value={data.value} onChange={data.onChange} />;
  ),

  styles: () => ({
    Input: styled.input`
      color: #000;
    `
  })
});

/* Equivalent regular syntax:
function Todo() {
  const [value, setValue] = useInputValue('test');

  function onChange(e) {
    setValue(e.target.value);
  }

  return <Input value={value} onChange={onChange} />;
}

function useInputValue(initial) {
  const [value, setValue] = useState(initial);
  return { value, setValue };
}

const Input = styled.input`
  color: #000;
`;

Object.assign(Todo, { hooks: { useInputValue }, styles: { Input } });
*/

// Using the static members
const App = () => {
  const [value, setValue] = Todo.hooks.useInputValue('test');
  return (
    <>
      <Todo />
      <Todo.styles.Input />
    </>
  );
};
Enter fullscreen mode Exit fullscreen mode

以上三种情况与上一节中提到的代码分割形式的三个层次完全对应。

我已经制作了一些使用此 API 管理不同 CSS-in-JS 库的示例,您可以在这里看到

为 React 中的 Split Editors 开发了一个 VS Code 插件。

我还制作了一个类似思路的 VS Code 插件:vscode-jsx-sfc。它需要配合使用jsx-sfc,以下是演示:

jsx-sfc 演示

与 Volar 类似,我们可以专注于在多个分屏编辑器中编写ComponentReact组件的render代码styles;同时,它还可以概览整个组件代码,从而减轻处理不同类别代码之间关系所带来的精神负担,并减少垂直滚动代码的长度。

如果您不习惯编写单独的渲染函数,拆分编辑器目前仍仅支持Component/ styles:

jsx-sfc 演示

如果单个文件中定义了多个函数组件jsx-sfc,则在每个拆分编辑器中,不相关的代码将针对每个组件进行折叠:

jsx-sfc 演示

如果使用 jsx-sfc 定义静态成员,它们将被拆分为Component and static//render形式styles

jsx-sfc 演示

如何快速体验

步骤 1:使用create-react-app创建一个示例项目:

npx create-react-app my-app
Enter fullscreen mode Exit fullscreen mode

步骤 2:安装jsx-sfc.macrostyled-components

cd my-app
npm install jsx-sfc.macro styled-components
Enter fullscreen mode Exit fullscreen mode

步骤 3:将此代码复制到src/App.js

import styled from 'styled-components';
import sfc from 'jsx-sfc.macro';
import logo from './logo.svg';

const App = sfc({
  Component({ styles: { Wrapper }, ...props }) {
    return (
      <Wrapper>
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.js</code> and save to reload.
          </p>
          <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer">
            Learn React
          </a>
        </header>
      </Wrapper>
    );
  },

  styles: () => {
    return {
      Wrapper: styled.div`
        text-align: center;

        .App-logo {
          height: 40vmin;
          pointer-events: none;
        }

        @media (prefers-reduced-motion: no-preference) {
          .App-logo {
            animation: App-logo-spin infinite 20s linear;
          }
        }

        .App-header {
          background-color: #282c34;
          min-height: 100vh;
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          font-size: calc(10px + 2vmin);
          color: white;
        }

        .App-link {
          color: #61dafb;
        }

        @keyframes App-logo-spin {
          from {
            transform: rotate(0deg);
          }
          to {
            transform: rotate(360deg);
          }
        }
      `
    };
  }
});

export default App;
Enter fullscreen mode Exit fullscreen mode

步骤 4:在 VS Code 中安装vscode-jsx-sfcSplit Editors Icon (搜索“jsx-sfc”),然后单击代码视图编辑器右上角的图标,即可开始体验:

jsx-sfc 演示

以上是在 CRA 中使用 Babel 宏进行体验的示例,其他框架如 Webpack、Rollup 和 Vite 也同样支持,只需进行相应替换即可jsx-sfc.macrojsx-sfc详情请参见此处。

非常感谢您的阅读。

这个 VS Code 插件目前肯定还不完美,但已经可以尝试用于日常开发了。它的实现使用了 @vue/reactivity,与 Volar 相同。

欢迎体验这款有趣的工具并提出建议,代码仓库和文档链接如下:

GitHub 标志 joe-sky / jsx-sfc

类似 SFC 的 React 函数组件 API,用于管理 CSS-in-JS 和静态成员。

文章来源:https://dev.to/joesky/i-made-a-vscode-plugin-that-c​​an-write-each-part-of-react-component-in-multiple-split-editors-on-the-same-screen-58a5