• 作者:老汪软件技巧
  • 发表时间:2024-09-06 07:01
  • 浏览量:

前言

大家好,我是抹茶。

之前自己整了个微信小程序,在迭代的过程中发现H5和微信侧的样式处理不一样,具体见于悲愤前行,记录那些我在开发uniapp(微信小程序方向)遇到的疑难杂症,主要体现在,微信侧生效的样式覆盖,在H5侧无效,在追踪问题的过程中,发现原因是uniapp会在H5侧默认对样式开启scoped,而其他侧默认不开启,而更深层原因是vue文件在style上写上scoped后会有特殊的样式转化,本文将记录这一探究过程。

问题追踪

解决思路: 查看H5和微信侧最终生成的样式有何区别?

确认方式: 使用开发者工具直接搜索css的相关类名,得到结果如下

H5侧的结果:

微信小程序的结果:

通过对比,可以发现H5侧多了小尾巴,增加了[data0v-4288271f],也就是把样式的作用范围缩小到拥有属性data0v-4288271f的DOM上,我们来看一下uniapp中的源码,并没有在style标签上添加scoped。

查一下uniapp的官方文档,关键词scoped

干得漂亮!所以差异点就出现在了scoped

style上的scoped到底做了什么事情呢?

查看Vue官方文档,如下

微信小程序文本框样式_微信样式表_

追查vue源码,发现,当配置了scoped,会调用scopedPlugin,文件位于compiler-sfc文件夹下面。

compiler-sfc是 Vue.js 中一个非常重要的编译器,它专门用于处理 Vue 的单文件组件(Single File Component,SFC)。SFC 是一种将模板、脚本和样式封装在一个 .vue 文件中的方式,极大方便了 Vue 组件的开发。

compiler-sfc 的主要功能

解析 SFC: compiler-sfc 会将 .vue 文件解析成一个 JavaScript 对象,这个对象包含了组件的模板、脚本和样式信息。

编译模板: 将模板中的语法(如 v-if、v-for 等)编译成渲染函数,以便 Vue 能够高效地渲染 DOM。

处理样式: 将组件中的样式信息提取出来,并根据配置进行处理(如 scoped CSS、CSS Modules 等)。

静态分析: 对组件进行静态分析,找出潜在的问题,例如未使用的变量、类型错误等。

scopedPlugin的定义见下图:

解析规则的关键函数如下图,它会在解析css选择器(selectorParser)后,重写选择器(rewriteSelector)

重写的过程中遇到>>>或者/deep/,会把当前选择器的前缀和后缀都置为空串。

可得,vue内部在遇到scoped后,会在style的处理过程中重写选择器,加上形如[data0v-4288271f]的后缀。

总结

uniapp 内部会默认给H5端的样式默认启用了 scoped,非H5端默认并未启用 scoped,导致H5端的样式作用范围更小。

Vue在style标签上增加scoped时,会默认给对应的css选择器尾部,增加形如[data0v-4288271f]的小尾巴,并在使用该选择器的DOM上增加属性data0v-4288271f,使得样式的作用范围,既要满足有匹配的css选择器,又要在DOM上拥有相应的属性,进一步缩小样式的影响范围。

Vue在内部通过postcss-selector-parser去解析css选择器,遵循(source string → tokens → AST)的过程,过程中遇到>>>或者/deep/,会把css选择器的前缀和后缀都置为空,从而扩大css选择器的范围,或者说让其不仅仅局限于当前组件。