🤔 当强迫症在Uniapp & Vue3中使用UnoCSS
引入方式大同小异,和开发Web项目的方式差不多,但是因为其是小程序,所以还需要进行一些调整
export default defineConfig({
// ...UnoCSS options
theme: {
preflightRoot: ['page,::before,::after']
}
})
小程序的根节点是 page
0️⃣ 编码习惯 🫠
我通常更倾向于 TailwindCSS 的那种写法,且会对不同类型的Class进行分行
于是我照常将这种写法用于 Uniapp 中,在微信开发者工具中得到了如下结果 ☹️
这里就得提到 Unocss 对于 x-[xx]
的编译结果了
text-[25px]
.text-\[25px\] {
font-size:25px;
}
结合上述的报错可以发现,是由这里的 \
所导致
那为了让自己写起来更舒服,于是就开始捣鼓该如何解决了 😋
1️⃣ And
text-[25px] -> text-_25px_
总结就是得让其不在小程序报错,所以需要对不支持的字符进行替换 👀
这里需要干涉 UnoCSS 以及 Vue 的编译
- UnoCSS:修改其编译结果(Class 名称,让其不在小程序中报错
- Vue: 还是处理编译结果中的 Class 名称,需要适应上述的修改
UnoCSS
https://unocss.dev/config/variants
文档中有提到,Config 中的 Variants 可以完成对编译结果中 Class 名称的自定义 🧐
variants: [
matcher => {
return {
matcher: matcher,
selector: (s: any) => {
if (/^(.+)?\[(.*)]$/.test(s)) {
let res: any = s.replace(/\[/g, '_').replace(/\]/g, '_')
s = res.replaceAll('\\', '')
}
if (s.includes(':')) {
s = s.replace(':', '_')
}
if (s.includes("'")) {
s = s.replaceAll("'", '-')
}
if (s.includes('"')) {
s = s.replaceAll('"', '-')
}
if (s.includes('#')) {
s = s.replaceAll('#', '-')
}
if (s.includes('/')) {
s = s.replaceAll('/', '-')
}
if (s.includes('%')) {
s = s.replaceAll('%', '-')
}
s = s.replaceAll('\\', '')
return s
},
}
},
],
- 第一个判断作用于对
[]
的处理 - 第二个判断作用于对
hover:
active:
... 的处理 - 第三以及第四对应
after:content-['']
after:content-[""]
的处理 - ...
export default defineConfig({
// ...UnoCSS options
theme: {
preflightRoot: ['page,::before,::after']
},
// ...variants
})
Vue
这里则是干涉 Vite 对 Vue 源码的编译,可以通过 Vite Plugin 实现
classHandlePlugin
export default function classHandlePlugin() {
return {
name: 'replace-class',
transform(code: string, id: string) {
if (id.endsWith('.vue')) {
const pattern = /class="([^"]*)"/g
code = code.replace(pattern, (_: any, className: string) => {
let classItems = className.split(' ')
classItems = classItems.map((item) => item.replace(/\n/g, ''))
classItems = classItems.filter((item) => item !== '')
classItems = classItems.map((item) => {
if (/^(.+)?(\-\[(.*)])(.+)?$/.test(item)) {
item = item.replace(/\[/g, '_').replace(/\]/g, '_')
if (item.includes('\'')) {
item = item.replaceAll('\'', '-')
}
if (item.includes('\"')) {
item = item.replaceAll('\"', '-')
}
if (item.includes('#')) {
item = item.replaceAll('#', '-')
}
if (item.includes('%')) {
item = item.replaceAll('%', '-')
}
}
if (item.includes('\/')) {
item = item.replaceAll('\/', '-')
}
if (item.includes(':')) {
item = item.replace(':', '_')
}
return item
})
className = classItems.join(' ')
return class="${className}"
})
}
return {
code
}
}
}
}
添加至 vite.config.ts
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import UnoCSS from 'unocss/vite'
import classHandlePlugin from './src/core/classHandlePlugin'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [classHandlePlugin(), uni(), UnoCSS()],
resolve: {
alias: {
'@': '/src'
}
}
})
这里需要注意,classHandlePlugin() 需要放置在最前面 🤔
2️⃣ Example
3️⃣ End
当然,光引入完也是能用的,只是对于那些会产生不受小程序所支持的字符才需要进行上述处理 👀
抛开中括号 []
可以采用类似 WindCSS 的写法
text-25px
.text-25px {
font-size:25px;
}
不过对于某些情况,上述的处理并不能完全覆盖到,比如动态Class的处理 :class='[]'
,需要进一步完善正则
小起
老哥,在hbuilderx中配置了,不报错了。编译后的class正常:m-[10rpx]变为了m-_10rpx_,但是css样式没有:m-_10rpx_{margin: 10rpx;} 这个没有出现
xiamo
@小起 如果配置都没有遗漏,那可以试试指定 UnoCSS 版本 `0.51.13`,另外,如果项目刚启动,建议用这个 uni-app 启动模板来初始化
https://github.com/uni-helper/vitesse-uni-app