公司项目需要开发一款平板应用,用于公司内部作业人员使用。考虑到使用人数较少、对应用性能无较高要求,决定沿用前端现有技术栈,最后使用cordova打包成套壳App的开发方案。由于拿到的平板系统过于老旧,所以出现了一些webview兼容性问题,下面记录了相应的问题和解决方案。
umijs兼容问题
问题: 打包之后,运行到平板上时,出现白屏等无法加载的问题,控制台有Uncaught TypeError报错。
原因: 因为webview版本太低,js很多新的语法不支持,所有需要解决webview即低版本浏览器的兼容问题。
方案: umi配置文件中,targets属性,可配置需要兼容的浏览器最低版本
umi官方配置文档
antd样式兼容问题
问题: 打包之后再运行到平板上时,App可以运行,但发现antd的样式失效了。
原因: antd v5中CSS-in-JS 默认通过 :where 选择器降低 CSS Selector 优先级,低版本浏览器不支持:where的写法。
方案: 使用 @ant-design/cssinjs 取消默认的降权操作
注意: 请注意版本保持与 antd 一致,自己没注意这句话,就踩坑里了,如果安装过@ant-design/cssinjs之后,再变更antd版本,对应的@ant-design/cssinjs要卸载重装
ant design 样式兼容
其他问题: 知道怎么配置了,不过一开始没找到项目的主入口文件中如何配置StyleProvider,后来在umi的运行时配置文档中找到了配置方法。
方案: umi的rootContainer配置,可以修改交给 react-dom 渲染时的根组件,在外面包一个 Provider。
export function rootContainer(container) {
return React.createElement(StyleProvider, {
hashPriority: 'high'
}, container);
}
其他问题: 配置完成之后,发现其他组件都正常,但是message、modal等组件的样式还存在问题
原因: 浏览器中调试发现message的样式还是:where书写方式,在平板上运行发现message组件的样式丢失了,结论认定还是message的样式中:where移除失败,后来提了issues,感谢antd项目人员的快速回复。原来antd message组件的文档里已记录了此常见问题
方案: 更改message的调用方式
// 通过App包裹组件的方式
import React from 'react';
import { App, Button} from 'antd';
// Sub page
const MyPage = () => {
const { message, modal, notification } = App.useApp();
const showMessage = () => {
message.success('Success!');
}
return (
<Button type="primary" onClick={showMessage}>
Open message
</Button> );
};
// Entry component
export default () => (
<App>
<MyPage />
</App>
);
rem适配方案
问题: 因为项目的优先级不高,所以没有安排UI设计高保真页面,由经理临时画了个原型,分辨率并未做考虑,再加上现在调试的平板和作业员手中的可能会有差异,用传统的px写法不适用,flex布局效果也不是太好。
方案: 最后决定采用rem的写法,来适配不同终端
// 通过js设置根字体大小 = *( 当前设备横向独立像素值 100) / 设计稿宽度
// 编写样式时,直接以rem为单位,值为:设计值 / 100
function adapter() {
const rootFontSize = document.documentElement.clientWidth * 100 / 1366
document.documentElement.style.fontSize = rootFontSize + "px"
}
adapter()
// 视口发生变化的时候触发
window.onresize = adapter
其他问题: 自己的页面适配了,antd的组件样式也要改成rem的方式
方案: antd 是支持配置px单位转rem的,直接按说明配置即可
import { StyleProvider, px2remTransformer } from '@ant-design/cssinjs';
// 往之前的rootContainer配置中加入对应的transformers
const px2rem = px2remTransformer({
rootValue: document.documentElement.clientWidth * 100 / 1366,
});
export function rootContainer(container) {
return React.createElement(StyleProvider, {
transformers: [px2rem]
, hashPriority: "high"
}, container);
}
antd 暗黑模式配置
方案: 使用antd提供的预设算法方案
import { StyleProvider, px2remTransformer } from '@ant-design/cssinjs';
import { ConfigProvider, theme } from 'antd';
// 在之前的rootContainer中嵌套一层ConfigProvider的配置即可
export function rootContainer(container:any) {
return React.createElement(StyleProvider, {
transformers: [px2rem]
, hashPriority: "high"
}, React.createElement(ConfigProvider, {
theme: { algorithm: theme.darkAlgorithm }
}, container));
}