记一次在 Vite + React 里如何使用 Unocss

4,844 阅读2分钟

theme: qklhk-chocolate highlight: github

前言

Unocss 是由 antfu 基于 WindiCSS 开发的,Unocss 将 JIT 再次发扬光大,使其更加的可定制化,同时下一代的 WindiCSS 将使用 Unocss 作为引擎。

本文使用的 Unocss 版本为 0.45.30。

配置环境

  • npm i -D unocss@0.45.30
  • main.tsx 中输入 import 'virtual:uno.css'
  • 添加 UnoCSS
//vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import UnoCSS from 'unocss/vite'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    UnoCSS(),
    react()
  ]
})
  • 在项目主目录下创建 uno.config.ts
// 以下代码需全部 cv 过去!!! 如果没有的话可能会引起 unocss 插件不起作用,导致没有提示
// uno.config.ts
import {
  defineConfig, presetAttributify, presetIcons,
  presetTypography, presetUno, transformerAttributifyJsx
} from 'unocss'

export default defineConfig({
  theme: {
  },
  shortcuts: {
   // 这里可以放全局公共样式
    'h-btn': 'h-48px w-100% bg-#5C33BE b-none text-white rounded-8px'
  },
  safelist: [],
  presets: [
    presetUno(),
    presetAttributify(),
    presetIcons({
      extraProperties: { 'display': 'inline-block', 'vertical-align': 'middle' },
    }),
    presetTypography(),
  ],
  transformers: [
    transformerAttributifyJsx()
  ],
})
  • 在 src 目录下新建 shims.d.ts
    • 这个文件的作用是对 TS 未识别的 unocss 属性进行声明
    • 如果在写 unocss 的时候,属性报错就需要在这里添加相应属性的类型
import * as React from 'react'
declare module 'react' {
  interface HTMLAttributes<T> extends AriaAttributes, DOMAttributes<T> {
    flex?: boolean
    relative?: boolean
    text?: string
    grid?: boolean
    before?: string
    after?: string
    shadow?: boolean
    w?: string
    h?: string
    bg?: string
    rounded?: string
    fixed?: boolean
    b?: string
    z?: string
    block?: boolean
    'focus:shadow'?: boolean
  }
  interface SVGProps<T> extends SVGAttributes<T>, ClassAttributes<T> {
    w?: string
    h?: string
  }
}

写法参考

uno.antfu

windicss 官网

案例

export const Welcome: React.FC = () => {
  return (
    <div flex justify-center items-center
      after="content-[hi] b-1 b-red"
      before="content-[hi] b-1 b-red"
      shadow
    >
      <header hover:bg-red w-100px b-1 b-red h-40px></header>
      <main grow-1 b-1 b-blue h-100px></main>
      <footer w-200px b-1 b-pink h-55px></footer>
    </div>
  )
}

unocss 的几种写法

<>
  // 第一种:使用中划线
  <header hover:bg-red w-100px b-1 b-red h-40px></header>
  // 第二种:使用 className
  <main grow-1 b-1 b-blue h-100px  className='text-2xl'></main>
  // 第三种:使用 =
  <footer b-1 b-pink h-55px w="100%"></footer>
  // 温馨提示: ⚠️在页面布局的时候,不要随便设置 h="100%" 会有bug
  
  // 使用 children- 的写法可以给子元素设置样式
   <ul children-px-24px >
     <li>😌</li>
   </ul>
</>

注意📌: unocss 在某些情况下不用 className 写法的话会有 bug,当发现写的属性不起作用的话: 可以使用 data-x='1' 去看是否加在了元素上,如果有则需要将不起作用的 unocss 属性使用 className 写法,同时 unocss 是不支持动态的设置 active 的样式 (点击的时候想要给被点击的元素设置样式,unocss 是无法动态设置的)。

// 如果我的值是动态的没有办法提前预知的可以用中括号括起来, 
// unocss 里面不允许有空格,需要用下划线来表示 eg: grid-cols="[20px_1fr_1fr]"
<>
  <div grid grid-cols="[auto_1fr_auto]" grid-rows-2 gap-x-12px b="#EEE" />
  <div grid grid-cols="[repeat(auto-fit,48px)]" />
  <div bg="[rgba(0, 0, 0, .5)]" />
  <div className="bg-black:5" />
  <div z="[var(--z-menu)]" />
  <div z="[calc(var(--z-default)_-_1)]" />
  <div z="[calc(var(--z-dialog)-1)]" />
  // `text-red-500/50` 如果需要用到 # 号的话可以写成 `text="#bd1000"`
  <div text-red-500/50 />
  <div text="#bd1000" />
</>

想改 shadow 样式可以新建 global.scss, 在 main.tsx 里全局导入 global.scss,同时记得 npm i sass

:root {
  --un-shadow-color: red;
}

预览效果:

截屏2023-02-15 10.43.31.png

如果是组件之间的传递该如何?

以下为 WelcomeScreen 组件在使用的时候,如果想传递需要写上 className

<WelcomeScreen animationData={groovyWalkAnimation} className="mt-200px"/>

组件内部需要使用 classnames 来添加多个类名

import c from 'classnames'
import React from 'react'
import Lottie from 'lottie-react'

interface Props {
  animationData: object
  className?: string
}

export const WelcomeScreen: React.FC<Props> = (props) => {
  const { className, animationData } = props
  return (
    <Lottie className={c(className, 'w-300px', 'h-300px', 'm-t--50px')} animationData={animationData} loop={true} />
  )
}

插件推荐

截屏2023-02-15 10.46.32.png

这个插件会在你鼠标悬浮到 unocss 属性上时,提示其对应的 CSS 代码是什么 截屏2023-02-15 10.47.24.png

截屏2023-02-15 10.48.38.png

参考链接