joken-前端工程师

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: :: :: 管理 ::
  404 随笔 :: 39 文章 :: 8 评论 :: 20万 阅读

在 Vue 3 中使用 TSX(TypeScript + JSX)时,情况与 React 有所不同。Vue 3 的 TSX 支持允许你在组件中以 JSX 的方式编写模板,但其样式处理的机制与 React 的内联样式或 CSS-in-JS 有所区别。Vue 3 的 TSX 本身并没有像 React 那样直接通过 style 属性绑定样式的标准惯例,而是更倾向于利用 Vue 的样式系统(如 <style> 标签)或结合外部 CSS 文件。不过,你仍然可以通过一些方式在 TSX 中“直接定义样式”。以下是详细说明和实现方式。


Vue 3 TSX 的样式处理背景

  • Vue 单文件组件(SFC):传统上,Vue 使用 <style> 标签在 .vue 文件中定义样式,支持 scoped 或全局样式。
  • TSX 模式:在 TSX 中,没有 <style> 标签,因此需要其他方式处理样式。
  • 支持程度:Vue 3 对 TSX 的支持是官方提供的(通过 @vue/babel-plugin-jsx),但样式处理不像 React 那样内置于 JSX 语法中。

在 Vue 3 TSX 中直接定义样式的实现方式

1. 内联样式(使用 style 属性)

与 React 类似,Vue 3 TSX 支持通过 style 属性直接为 JSX 元素绑定内联样式。样式以 JavaScript 对象的形式传入,并且可以用 TypeScript 类型(如 CSSProperties)进行约束。

示例
import { defineComponent } from "vue";

export default defineComponent({
  setup() {
    const divStyle: CSSProperties = {
      backgroundColor: "blue",
      color: "white",
      padding: "10px",
      borderRadius: "5px",
    };

    return () => (
      <div style={divStyle}>
        Hello, Vue 3 TSX!
      </div>
    );
  },
});
类型支持
  • Vue 3 TSX 默认支持 style 属性,但没有像 React 那样的 React.CSSProperties 类型。你可以手动引入或定义:
    interface CSSProperties {
      [key: string]: string | number | undefined;
    }
    
动态样式示例
import { defineComponent, ref } from "vue";

export default defineComponent({
  setup() {
    const isActive = ref(false);

    const boxStyle: CSSProperties = {
      width: "100px",
      height: "100px",
      backgroundColor: isActive.value ? "green" : "red",
      transition: "background-color 0.3s",
    };

    const toggle = () => {
      isActive.value = !isActive.value;
    };

    return () => (
      <div style={boxStyle} onClick={toggle}>
        Click me
      </div>
    );
  },
});
特点
  • 优点:简单直接,支持动态样式。
  • 缺点:与 React 相同,不支持伪类(如 :hover)或媒体查询。

2. 在组件中定义并复用样式对象

类似于 React,你可以在组件中定义样式对象并复用,但这种方式仍是内联样式的变种。

示例
import { defineComponent } from "vue";

export default defineComponent({
  setup() {
    const commonStyle: CSSProperties = {
      fontSize: "16px",
      margin: "10px",
    };

    const containerStyle: CSSProperties = {
      ...commonStyle,
      backgroundColor: "lightgray",
    };

    const textStyle: CSSProperties = {
      ...commonStyle,
      color: "blue",
    };

    return () => (
      <div style={containerStyle}>
        <span style={textStyle}>Styled Text</span>
      </div>
    );
  },
});
特点
  • 复用性:通过对象扩展实现样式共享。
  • 局限性:仍然受限于内联样式的特性。

3. 使用 CSS 模块

Vue 3 TSX 支持 CSS 模块,但需要手动引入外部 CSS 文件(.module.css.module.scss),并在 TSX 中通过 class 属性应用样式。这种方式不算“直接在组件中定义”,但非常实用。

示例
/* styles.module.css */
.container {
  background-color: lightblue;
  padding: 20px;
}

.text {
  color: darkblue;
}
import { defineComponent } from "vue";
import styles from "./styles.module.css";

export default defineComponent({
  setup() {
    return () => (
      <div class={styles.container}>
        <span class={styles.text}>Hello, Vue 3 TSX!</span>
      </div>
    );
  },
});
配置
  • 需要确保项目支持 CSS 模块(例如通过 Vite 或 Webpack 配置)。
  • Vite 示例(vite.config.ts):
    import { defineConfig } from "vite";
    import vue from "@vitejs/plugin-vue";
    
    export default defineConfig({
      plugins: [vue()],
      css: {
        modules: {
          localsConvention: "camelCase",
        },
      },
    });
    
特点
  • 优点:支持完整 CSS 特性(如伪类、媒体查询),样式隔离。
  • 缺点:需要外部文件,不完全是“组件内定义”。

4. 使用 styled-components 或 CSS-in-JS

Vue 3 TSX 也可以结合 styled-components@emotion/styled 等 CSS-in-JS 库,直接在组件中以模板字符串定义样式。这种方式需要额外安装库,但与 React 的用法类似。

示例(使用 styled-components
import { defineComponent } from "vue";
import styled from "styled-components";

const StyledDiv = styled.div`
  background-color: purple;
  color: white;
  padding: 15px;
  border-radius: 8px;
`;

export default defineComponent({
  setup() {
    return () => <StyledDiv>Hello, Vue 3 TSX!</StyledDiv>;
  },
});
配置
  • 安装依赖:npm install styled-components @types/styled-components vue3-jsx.
  • 注意:Vue 3 TSX 对 styled-components 的支持需要额外的 Babel 或 Vite 配置,确保 JSX 插件正确解析。
特点
  • 优点:动态样式、封装性强。
  • 缺点:依赖第三方库,增加复杂性。

与 Vue SFC 的 <style> 对比

  • SFC 方式.vue 文件):
    <template>
      <div class="container">Hello</div>
    </template>
    <style scoped>
    .container {
      background-color: blue;
      color: white;
    }
    </style>
    
  • TSX 方式:没有内置的 <style> 支持,必须通过内联样式、CSS 模块或 CSS-in-JS 实现。

注意事项

  1. Vue 3 TSX 的局限性

    • 没有像 SFC 那样的 scoped 样式支持,内联样式或 CSS 模块需要手动管理作用域。
    • 默认不支持直接在 TSX 中嵌入 <style> 标签。
  2. 类型支持

    • 内联样式可以用自定义的 CSSProperties 接口或从 React 类型中借用 React.CSSProperties
      import { CSSProperties } from "react"; // 可选
      
  3. 性能

    • 内联样式每次渲染都会生成新对象,建议将静态样式提取为常量。
  4. 工具链

    • 确保项目使用 @vue/babel-plugin-jsx(webpack)或 @vitejs/plugin-vue-jsx(Vite)支持 TSX。

总结:Vue 3 TSX 中定义样式的几种方式

方法 如何实现 优点 缺点
内联样式 style={{ key: value }} 简单、动态性强 无伪类支持,性能稍差
样式对象复用 定义样式对象并复用 代码清晰,可复用 仍受内联样式限制
CSS 模块 引入 .module.css 文件 隔离性好,支持完整 CSS 需要外部文件
CSS-in-JS 使用 styled-components 等库 动态性强,样式封装 依赖第三方库,配置复杂

推荐使用场景

  • 简单样式:直接用内联样式。
  • 动态样式:内联样式或 styled-components
  • 复杂项目:CSS 模块或 CSS-in-JS。
  • SFC 风格:如果需要 <style scoped>,建议使用 .vue 文件而非 TSX。
posted on   joken1310  阅读(66)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示