xChar
·6 months ago

浅析 uni-app-x 样式解析

本文相当于带读 @dcloudio/uni-nvue-styler 项目作用和结构,并介绍了如何验证实际效果。

举的例子是 uni-app-x 在 iOS 平台的例子,实际 Android 平台, nvue 平台操作步骤一样。

平台限制

在处理跨平台 css 处理时候,有一些需求和网页端不同:

  • 跨端不能完整支持所有 css 写法,是 css 规则的子集
  • 跨端自带的 css 默认值需要和 web、小程序对其
  • 跨端 css 需要考虑 class 定义、style 定义、style 运行时切换定义
  • 跨端子元素样式不能继承父元素样式

这里解释 uni-app-x 的 ios 部分是如何解析样式的。样式是一个重要且特殊的逻辑部分。

技术上讲,本质还是一些自定义的 postcss 插件来解析用户传递的样式,和客户端平台配合,将一些特殊的样式进行转写修改。

源码位置

uni-app 仓库 是指 github 上的 next 分支。

存在 @dcloudio/uni-nvue-styler 包。

  • 样式测试文件 packages/uni-nvue-styler/__tests__/normalize.spec.ts
  • 主逻辑 packages/uni-nvue-styler/src/index.ts

其中主逻辑部分逻辑入口文件

export { expand } from './expand'
export { normalize } from './normalize'
export { objectifier } from './objectifier'
export { parse } from './parse'

一条 css 规则转换的奇妙旅行!

技术上解释:

  • 是自定义了两个 postcss 插件 expandnormalize,交给 postcss 进行处理。
  • 得到的结果交给 objectifier 转为客户端接受的对象类型

parse 字符串解析

这是核心主方法,通过 postcss 进行语法转换,进一步转成对象。

expand 展开

两个 postcss 插件之一。常见的 css 逻辑缩写展开成多条最小规则

比如 border/background/transition 等等

举例 transition: margin-top 500ms ease-in-out 1s 这一条样式需要展开成多条规则

normalize 标准化处理

两个 postcss 插件之一。承接上一条拆开的 css 规则,讲值进一步调整,比如长度单位、非法值统一处理。

比如 width:200px -> 去除单位 200
比如 width: a -> 非法值会忽略并告警 比如 color: #f00 -> 补全 #ff0000
比如transition/font-face

objectifier 字符串转对象

处理好之后的 css 规则转化为对象,形成当前页面、组件下的样式规则集合。

举例,字符串 .abc{color:red} 会转换成类似下面的对象。这里的空字符串是为了支持其他的 css 选择器,比如子代选择器 .a .b。比如直接子代选择器 > 等。

举例,处理 !important 在具体的样式前面添加 !

var abc = {
  "":{
    color:'red'
  },
  ".bar ":{
    left: 2
  }
}

阅读理解源码

如果日常使用时候遇到了 bug,需要修复问题或者补充新功能,就需要阅读、调试源码。

因为这部分逻辑比较抽象,最适合的方案是阅读测试用例,从而进一步理解每个步骤的作用。

如何验证是否生效

有时候会做 feature/fix 改动,如果完成了代码改动,补充了对应的单元测试,如何验证改动效果?

这里做个流程总结:

  • 构建 @dcloudio/uni-nvue-styler 产物
  • 替换 HBuilderX 产物
  • 验证效果

构建产物

修改 uni-nvue-styler 需要执行构建,可以直接执行

pnpm run build nvue-styler

得到产物包,定位 dist 文件夹

替换产物

打开 HBuilderX 的包内容,注意我这里是内部的 -Dev 版本:

/Applications/HBuilderX-Dev.app/Contents/HBuilderX/plugins/uniapp-cli-vite/node_modules/@dcloudio/uni-nvue-styler/dist

替换刚才的 dist 文件,应该是三个文件。

重启后重新编译,应该就可以看到修改后的效果了。

总结

说明了 uni-app 项目 next 分支的 @dcloudio/uni-nvue-styler 作用。

并说明如何理解、调试、验证。

Loading comments...