postcss-mobile-forever icon indicating copy to clipboard operation
postcss-mobile-forever copied to clipboard

开启unocss的 @apply 转换后,针对style里面的@apply指定的unocss的尺寸类样式不会转viewport单位

Open Vinsurs opened this issue 1 year ago • 8 comments

unocss.config.ts

import {
  defineConfig,
  presetAttributify,
  presetIcons,
  presetMini,
  presetUno,
  transformerDirectives
} from 'unocss'
import presetRemToPx from '@unocss/preset-rem-to-px'

export default defineConfig({
  presets: [
    presetUno,
    presetAttributify,
    presetIcons(),
    // 为什么要用到这个插件?
    // 模板使用 viewport 作为移动端适配方案,unocss 默认单位为 rem
    // 所以需要转成 px,然后由 postcss 把 px 转成 vw/vh,完成适配
    presetRemToPx({
      // 这里为什么要设置基础字体大小?看下面这篇文章
      // https://juejin.cn/post/7262975395620618298
      baseFontSize: 4,
    }),
    presetMini(),
  ],
  shortcuts: [
    // shortcuts to multiple utilities
    ['btn', 'px-6 py-3 rounded-3 border-none inline-block bg-green-400 text-white cursor-pointer !outline-none hover:bg-green-600 disabled:cursor-default disabled:bg-gray-600 disabled:opacity-50'],
  ],
  transformers: [
    transformerDirectives({
      applyVariable: false,
    })
  ],
})

vite.config.ts

export default {
...,
css: {
      postcss: {
        plugins: [
          autoprefixer(),
          // https://github.com/wswmsword/postcss-mobile-forever
          viewport({
            appSelector: '#app',
            viewportWidth: 375,
            maxDisplayWidth: 600,
            rootContainingBlockSelectorList: [
              'van-tabbar',
              'van-popup',
            ],
            border: true,
          }),
        ],
      },
    }
}

然而我在组件中使用@apply写法时

<div class="item">...</div>

<style scoped lang='scss'>
.item {
//  这里text-[14px] 并不会转viewport单位,在浏览器审查样式时,仍然是font-size: 14px;
 @apply text-[#333333] text-[14px];
}
.other {
 @apply text-[12px];
}
</style>

预期: 这里text-[14px] 会转viewport单位

实际: 这里text-[14px] 并不会转viewport单位,在浏览器审查样式时,仍然是font-size: 14px; 并且.other 类中的 text-[12px] 任意值写法并没有生成对应的class样式类!

Vinsurs avatar Dec 11 '24 03:12 Vinsurs

"vue": "^3.5.6", "vite": "^5.4.6", "unocss": "0.62.4", "@unocss/preset-rem-to-px": "0.62.4", "postcss-mobile-forever": "^4.1.6",

Vinsurs avatar Dec 11 '24 03:12 Vinsurs

了解下其它 PostCSS 插件是否也无效?

wswmsword avatar Dec 11 '24 05:12 wswmsword

@wswmsword 其他Postcss有执行的。我的问题是行内unocss原子类使用你的插件确实会把px转viewport单位,但是@apply 指定的就不行了,甚至@apply中的 text-[12px]原子类不会生成对应的样式类, 但是text-[14px]就会生成但是生成的单位是px不是viewport单位

Vinsurs avatar Dec 11 '24 07:12 Vinsurs

我本地试了一下,UnoCSS 的 at-apply 样式不走 PostCSS 插件,请问你知道原因吗?我不太熟 UnoCSS。这个问题之前也提过 https://github.com/wswmsword/postcss-mobile-forever/issues/47

wswmsword avatar Dec 11 '24 12:12 wswmsword

@wswmsword 我本地写了个postcss插件测试了下,默认情况下交给postcss插件处理时的style中的css规则是未经过unocss 的transformerDirectives转换器转换过的,也就是还是我们源码的@apply这种,你这个插件要匹配这种的话应该要在postcss的AtRule 钩子中处理;但是这也污染了你这个插件的纯粹性吧;解决办法就是配置unocss的transformerDirectives转换器的执行时机,

transformerDirectives({
      ...,
     enforce: "pre"
})

这样就行了;此时posctcss拿到的css样式就是已经经过unocss转换器转换过的样式了

Vinsurs avatar Dec 16 '24 02:12 Vinsurs

默认情况 at-rule 样式应该也不会处理 unocss 的 @apply,mobile-forever 里实际上也处理了 at-rule。

设置 enforce: "pre" 这个方法怎么样,没啥副作用吧,我本来想是不是要实现个 transformerDirectives 插件的。

wswmsword avatar Dec 16 '24 02:12 wswmsword

@wswmsword 目前我这边是没啥副作用,设置之后就是转换@apply时机提前了而已

Vinsurs avatar Dec 16 '24 03:12 Vinsurs


import { transformerDirectives } from 'unocss';
export default defineConfig(({ mode }) => {
  return {
    plugins: [
     Unocss({
            transformers: [
              transformerDirectives({
                enforce: 'pre',
              }),
            ],
          }),
    ]
      }
});

实测有效,暂未出现异常

tnnevol avatar Aug 20 '25 01:08 tnnevol