UnoCSS给了我一个不用tailwindcss的理由

news2024/11/23 6:56:13

相同的原由 & 前言

如果你没有听说过 tailwindcss 或者 unocss,请先 return 先去了解一下😝。

  • 开发上:可能为你甚至你们的前端团队节省很多写样式的时间,也能让你或者你们的项目开发体验有很大提升
  • 生产上:你们的项目打出来的包体积中的样式代码占比将突然骤降然后趋于不变

书接上回

之前我写过一篇文章给我一个你不用tailwindcss的理由!,极力推荐使用 tailwindcss 来提升开发效率和体验,尤其是样式代码的体验会有质的提升。当然样式代码打包体积的减少也可以起到优化我们整体前端项目的作用。但是为什么有这篇文章了呢?因为托尼老师给了我不用 tailwindcss 的理由,无法拒绝的理由,就是我们今天的主角 UnoCSS

为什么我换到了UnoCSS

tailwindcssUnoCSS 都是原子化CSS模式实现的一种,为什么现在我更推荐 UnoCSS ,接下来就讲一下 UnoCSS 的杀手级亮点:

极致性能

这里我借用托尼老师的话:

No parsing, no AST, no scanning, it’s INSTANT (5x faster than Windi CSS or Tailwind JIT).

跳过解析,不使用 AST

从内部实现上看,Tailwind 依赖于 PostCSS 的 AST 进行修改。考虑到在开发过程中,这些工具 CSS 的并不经常变化,UnoCSS 通过非常高效的字符串拼接来直接生成对应的 CSS 而非引入整个编译过程。同时,UnoCSS 对类名和生成的 CSS 字符串进行了缓存,当再次遇到相同的实用工具类时,它可以绕过整个匹配和生成的过程。

现在说是比 tailwindcss 快5倍,其实当年可是比 tailwindcss JIT 模式快200倍的存在,后面 tailwindcss 应该是做了大量的优化工作,才让托尼老师改口称5倍快了😜。

完全可定制,不是一个框架,而是引擎

相比于 tailwindcss 必须把原子类写到 class 里面, UnoCSS 提供了更多可选方案,并且兼容多种风格的原子类框架,除了 tailwindcss ,同样支持 BootstrapTachyonsWindi CSS

属性化模式

这个模式也是由 Windi CSS 启发而来:
Attributify preset

// install
pnpm add -D @unocss/preset-attributify

// uno.config.ts
import { defineConfig } from 'unocss'
import presetAttributify from '@unocss/preset-attributify'

export default defineConfig({
  presets: [
    presetAttributify({ /* preset options */ }),
    // ...
  ],
})

🌰:

<div class="m-2 rounded text-teal-400" />
<!-- 现在你可以这么写: -->
<div m-2 rounded text-teal-400 />

前缀组,解决繁琐的多次写前缀的情况

Variant group transformer

// install
pnpm add -D @unocss/transformer-variant-group

// uno.config.ts
import { defineConfig } from 'unocss'
import transformerVariantGroup from '@unocss/transformer-variant-group'

export default defineConfig({
  // ...
  transformers: [
    transformerVariantGroup(),
  ],
})

比如我们在设置字体的时候常常会设置颜色、大小,或者在 hover 的情况下改动多个属性我们就可以这样🌰:

<div class="hover:bg-gray-400 hover:font-medium font-light font-mono"/>
<!-- 简化之后: -->
<div class="hover:(bg-gray-400 font-medium) font-(light mono)"/>

快捷方式和指令

Directives transformer

// install
pnpm add -D @unocss/transformer-directives

// uno.config.ts
import { defineConfig } from 'unocss'
import transformerDirectives from '@unocss/transformer-directives'

export default defineConfig({
  // ...
  transformers: [
    transformerDirectives(),
  ],
})

用过 tailwindcss 的同学都知道, tailwindcss 有指令系统,其中的 @layer components 指令可以把通用的样式 layer 到一个类上:

@layer components {
  .btn-blue {
    @apply bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded;
  }
}

UnoCSS 有类似的更好用快捷方式来快捷实现这个功能:

shortcuts: [
  // you could still have object style
  {
    btn: 'py-2 px-4 font-semibold rounded-lg shadow-md',
  },
  // dynamic shortcuts
  [/^btn-(.*)$/, ([, c]) => `bg-${c}-400 text-${c}-100 py-2 px-4 rounded-lg`],
]

另外还有一个使用很频繁的指令 @apply ,这个指令在以下两种情况下比较合适使用:

  • 有一个样式很多,很复杂的元素,直接写到标签里面会影响代码可读性
  • 同样的样式应用到很多元素上

🌰:

<div text-lg text-pink-400 font-bold border-1 border-gray border-dashed rounded flex flex-warp items-center justify-evenly>
  我的样式很复杂的
</div>
<button text-green-500 rounded hover:text-lg shadow-md>查询</button>
<button text-green-500 rounded hover:text-lg shadow-md>提交</button>
<button text-green-500 rounded hover:text-lg shadow-md>取消</button>

就可以这么优化:

<div class="complex-node">
  我的样式很复杂的
</div>
<button class="btn">查询</button>
<button class="btn">提交</button>
<button class="btn">取消</button>

<style>
.complex-node {
  @apply text-lg text-pink-400 font-bold border-1 border-gray border-dashed rounded flex flex-warp items-center justify-evenly;
}
.btn {
  @apply text-green-500 rounded hover:text-lg shadow-md;
}
</style>

构建合并多个原子类到一个类

Compile class transformer

// install
pnpm add -D @unocss/transformer-compile-class

// uno.config.ts
import { defineConfig } from 'unocss'
import transformerCompileClass from '@unocss/transformer-compile-class'

export default defineConfig({
  // ...
  transformers: [
    transformerCompileClass(),
  ],
})

这个特性一般比较少用,也可以看下是什么作用,通过 :uno: 标记,可以最终编译为一个类:

<div class=":uno: text-center sm:text-left">
  <div class=":uno: text-sm font-bold hover:text-red"/>
</div>

最终编译的结果:

<div class="uno-qlmcrp">
  <div class="uno-0qw2gr"/>
</div>
.uno-qlmcrp {
  text-align: center;
}
.uno-0qw2gr {
  font-size: 0.875rem;
  line-height: 1.25rem;
  font-weight: 700;
}
.uno-0qw2gr:hover {
  --un-text-opacity: 1;
  color: rgba(248, 113, 113, var(--un-text-opacity));
}
@media (min-width: 640px) {
  .uno-qlmcrp {
    text-align: left;
  }
}

检查器,可以详细的预览我们项目中的所有原子类

我们在启动开发服务器之后,可以直接访问localhost:5173/__unocss 就会看到这个画面:

image.png
直接就可以看到所有的原子类,具体某个组件中的原子类,打包后的体积等信息。

你的项目太老也想用?安排!

有些同学可能还在维护很老的前端项目,但是也想用上 UnoCSS 来提升开发体验, UnoCSS 提供了 CDN 版本,在前端的入口 index.html 文件中添加一行代码就可以支持,并且还支持配置💪:

<script src="https://cdn.jsdelivr.net/npm/@unocss/runtime"></script>
<script>
// pass unocss options
window.__unocss = {
  rules: [
    // custom rules...
  ],
  presets: [
    // custom presets...
  ],
  // ...
}
</script>

VS Code 插件当然也有

UnoCSS - Visual Studio Marketplace

你以为到这里就结束了?

再来给你看个好东西!

Icons preset (unocss.dev)

可以在 UnoCSS 中轻松集成纯 CSS 图标,可以在这里查看所有可用图标,想用哪种就可以安装对应的包即可:

// uno.config.ts
import { defineConfig } from 'unocss'
import presetIcons from '@unocss/preset-icons'

export default defineConfig({
  presets: [
    presetIcons({ /* options */ }),
    // ...other presets
  ],
})

没有你们设计中意的图标,UI 自己设计的图标也可以轻松集成,首先安装工具:

pnpm install -D @iconify/utils

然后把设计老师给的 svg 图标文件放到一个文件夹,我这里就放到src/assets/svg中,然后想一个图标名称,这里就叫 icon

// unocss.config.ts
import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders'
import {
  defineConfig,
  presetAttributify,
  presetIcons,
  presetUno,
} from 'unocss'

export default defineConfig({
  presets: [
    presetUno(),
    presetAttributify(),
    presetIcons({
      collections: {
        icon: FileSystemIconLoader(
          './src/assets/svg',
          svg => svg.replace(/#FFF/, 'currentColor'),
        ),
      },
      scale: 1.5,
      warn: true,
    }),
  ],
})

可以看到配置中 collections 里面有一个 icon 对象,这个名称就对应了我们刚才说的 icon 名称,对应的是一个 FileSystemIconLoader 方法,方法的第一个参数是你的图标在项目中的路径,我这里就是 ./src/assets/svg,按照相对路径就可以,也可以通过第二个参数做一些特殊预处理操作,具体可以看这个文档,这样配置完成之后,我们就可以在项目使用了。

比如我在src/assets/svg文件夹中放了一个 cancel.svg 的取消图标,我在页面上使用就可以这样写:

<div text-lg text-red inline-block i-icon:cancel />

其中的 i-icon 就是我们前面配置的自定义图标集的名称,冒号后面跟的就是你的 svg 图标的名称,可以通过样式改变图标的大小和颜色,是不是很酷😎。

丰富、灵活、开放的预设生态

UnoCSS 提供了丰富的预设,以支持不同风格体系的前端开发者,生态很完善,在 UnoCSS 发布之后我在很多项目中都应用实践过,基本可以覆盖所有样式场景。

总结

原子化CSS 的理念早已不是新鲜事物了, tailwindcssUnoCSS 这类解决方案把这个理念有了一个很好的实践和实现,可以真正的提升开发者体验和编码效率,都是很值得一学的技术。最后,有用请点赞,喜欢请关注,我是Senar,我们下一篇再见~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/650838.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VS2013创建一个MFC工程的步骤

目录 1、新建项目&#xff0c;选择”MFC应用程序“&#xff1b; 2、应用程序类型&#xff0c;选择“基于对话框”&#xff1b; 3、对话框的标题&#xff0c;默认是和项目的名字一致&#xff0c;按需修改&#xff1b; 4、高级功能&#xff0c;可以保持默认&#xff1b; 5、…

一个女测试工程师的大厂日常

今天给大家分享两个朋友的故事&#xff0c;他们分别在国内两家顶尖的互联网大厂&#xff0c;一个在头条&#xff0c;一个在蚂蚁。 头条的故事 头条的主人公&#xff0c;在入职后的一年里&#xff0c;晚上十点半下班是比较早了&#xff0c;基本上都是十一点半左右下班&#xff…

低成本开发专属小程序支持自定义开发设计

传统定制开发小程序成本高&#xff0c;还需要不断地沟通和交流才能一步步地去实现你想要的功能和效果&#xff0c;那么除了传统的定制开发小程序外&#xff0c;用户其实还可以选择使用模板开发小程序&#xff0c;不仅能实现小程序的所有基础功能&#xff0c;还不用编程维护和开…

进程的描述与控制

文章目录 前趋图和程序执行前趋图程序顺序执行程序并发执行 进程引入目的进程的描述进程的定义进程的特征进程的基本状态与转换挂起操作和进程状态的转换挂起操作引入引入挂起操作后进程3个基本状态间的转换引入挂起操作后进程5个基本状态间的转换进程管理中的数据结构OS中用于…

antdb-upgrade大版本升级介绍

antdb-upgrade pg_upgrade 是postgresql 大版本升级的得力工具。 数据库系统数据部分通过 new version的pg_upgrade自动升级完成数据库用户数据部分&#xff0c;主要有两种用法&#xff1a; 使用pg_upgrade copy物理拷贝方式升级(非copy to/copy from逻辑拷贝)。使用pg_upgra…

内网渗透—隧道搭建SPP与NPS内网穿透

内网渗透—隧道搭建&SPP与NPS内网穿透 1. 前言2. SPP2.1. SPP代理通信2.1.1. 服务端配置2.1.2. 客户端配置2.1.3. CS设置2.1.3.1. 设置生成的监听器2.1.3.2. 设置监听的监听器 2.1.4. 执行效果 2.2. SPP隧道建立2.2.1. 服务端设置2.2.2. 客户端配置2.2.3. CS设置2.2.3.1. 设…

Mybatis学习笔记三

目录 一、MyBatis的缓存1.1 MyBatis的一级缓存1.2 MyBatis的二级缓存1.3 二级缓存的相关配置1.4 MyBatis缓存查询的顺序1.5 整合第三方缓存EHCache&#xff08;了解&#xff09; 二、MyBatis的逆向工程2.1 创建逆向工程的步骤2.2 简单使用查询增改 三、 分页插件3.1 分页插件使…

Endnote解决文章题目Title大小写问题,以及专有名词保持全部大写

在写毕业论文或综述类文章时&#xff0c;需要添加大量参考文献&#xff08;100左右或更多&#xff09;&#xff0c;而每个期刊的要求是不一样的&#xff0c;因此手动输入或修改参考文献的格式是愚蠢的&#xff08;狗头保命&#xff09;&#xff0c;所以需要强大的endnote来进行…

一篇博客搞定C++11之Lambda表达式(附案例代码+解析)

Lambda表达式 1.lambda表达式语法2.捕获列表说明3.lambda表达式实现原理4.具体案例5.总结 1.lambda表达式语法 ambda表达式的语法非常简单&#xff0c;具体定义如下&#xff1a; [ captures ] ( params ) specifiers exception -> ret { body } 先不用急于解读这个定义&…

面向对象内部类

概念 将一个类 A 定义在另一个类 B 里面&#xff0c;里面的那个类 A 就称为内部类 &#xff08;InnerClass&#xff09;&#xff0c;类 B 则称为外部类&#xff08;OuterClass&#xff09; 根据内部类声明的位置&#xff08;如同变量的分类&#xff09;&#xff0c;我们可以分…

首次使用云服务器搭建网站(二)

书接上文&#xff0c;我们已经完成了服务器的租赁&#xff0c;宝塔面板的下载与安装。 接下来我们将正式开始网站搭建。 一、网站创建 点击网站、添加站点 输入网站域名、数据库选择MySQL数据库&#xff0c;选择utf8&#xff0c;数据库账号密码会自动生成。无论你要创建什么样…

【linux网络配置】多个网卡一起使用,一个网卡连内网,一个网卡连外网

一、问题背景 因为有一个工作站在内网中&#xff0c;但是没有办法联网&#xff08;校园网账户有限&#xff09;。 虽然工作站没有联网&#xff0c;但是我仍然可以通过局域网远程控制工作站&#xff0c;使其访问校园网验证页面实现上网。 当给工作站安装软件或依赖项时&#…

SpringBoot配置文件application.properties的理解

一、存放位置分类 1.当前项目根目录下的config目录下 2.当前项目的根目录下 3.resources目录下的config目录下 4.resources目录下 按照这上面的顺序&#xff0c;4个配置文件的优先级依次降低。 我们在项目里面4个位置分别设置了各种的application.properties文件。每个文件…

MySQL查看和修改最大连接数

标题&#xff1a;MySQL查看和修改最大连接数 MySQL 是一种广泛使用的开源关系型数据库管理系统&#xff0c;被许多应用程序用作其后端存储解决方案。在高并发的环境下&#xff0c;MySQL 的最大连接数变得尤为重要。本文将介绍如何查看当前的最大连接数&#xff0c;并详细说明每…

安卓实战开发之——使用 WIFI 进行设备搜索并获取相应信息

目录 一、前言 二、准备条件 三、功能要求 四、显示效果 五、关键代码 一、前言 此玩意是本人很早很早&#xff08;记不清有多早了&#xff0c;反正很早&#xff09;做过的一个课程任务了&#xff0c;无意之中翻到了&#xff0c;所以把它放上来。不愿再找以前写的代码了…

大数据环境搭建 Hadoop+Hive+Flume+Sqoop+Azkaban

目录 零&#xff1a;版本说明一、安装CentOS二、Hadoop单机配置三、Hive安装部署 零&#xff1a;版本说明 Hadoop&#xff1a;3.1.0 CentOS&#xff1a;7.6 JDK&#xff1a;1.8 一、安装CentOS 这里网上教程很多&#xff0c;就不贴图了 【内存可以尽量大一些&#xff0c;不然…

DeepBIO:一个自动化和可解释的深度学习平台,用于高通量生物序列预测,功能注释和可视化分析

DeepBIO: an automated and interpretable deep-learning platform for high-throughput biological sequence prediction, functional annotation and visualization analysis 期刊&#xff1a;Nucleic Acids Research 中科院分区&#xff1a;2区 影像因子&#xff1a;19.1…

面向对象抽象

抽象类 1 概念 Java中可以定义被abstract关键字修饰的方法,这种方法只有声明,没有方法体,叫做抽象方法. Java中可以定义被abstract关键字修饰的类,被abstract关键字修饰的类叫做抽象类 如果一个类含有抽象方法,那么它一定是抽象类 抽象类中的方法实现交给子类来完成 2 抽象…

redisTemplate海量数据批量存储

有个表的数据需初始化到redis, 目前18w, 后期会达到千万1. 使用redisTemplate批量存储数据 Autowiredprivate RedisTemplate redisTemplate;public void init(){List<WxPois> list SpringUtils.getBean(WxPoisMapper.class).selectWxPoisList(new WxPois());if (Collect…

华为OD机试之数组拼接(Java源码)

数组拼接 题目描述 现在有多组整数数组&#xff0c;需要将它们合并成一个新的数组。 合并规则&#xff0c;从每个数组里按顺序取出固定长度的内容合并到新的数组中&#xff0c;取完的内容会删除掉&#xff0c;如果该行不足固定长度或者已经为空&#xff0c;则直接取出剩余部…