最近,一批使用小米最新版的用户反馈,app 内的部分样式不兼容,但大部分的组件是正常的!
就这样下面这样:
图中,【工作对象】和【签名】区域是自定义的局部注册组件,像【更多信息】是全局注册组件。
刚开始以为是小米最新版系统不兼容 flex
布局和 vw/vh
等属性,但若真是这样不应该所有组件都有问题吗?
先直接说解决方法吧。
解决方法
方法一
将组件的局部样式改成 style
形式的内联样式(组件太多人会麻),就像这样:
方法二
方法三
修改 Vue 配置,比如在 vue.config.js
配置文件中配置 css.extract: false
注:虽然在生产环境配置 css.extract: false 有一定的缺点,但在这里为了解决兼容性问题,不得不这么配置
目的是为了在打包时不将组件中的 CSS 提取至一个独立的 CSS 文件中,而是将 CSS 样式动态注入到 JavaScript
中的 inline
代码中。
就像这样,dist1 是 css.extract: true
的打包结果,css 样式会被提取至独立的 CSS 文件;dist2 是css.extract: false
的打包结果,区别就是 dist2 中的 CSS 是内联在 JS 代码中。
原因
原因是小米最新版手机在读 CSS 文件有问题,它只识别了全局注册组件的样式。
这是因为全局组件是在 Vue 应用初始化时加载的;而局部组件,它是在父组件实例时才加载的,对于没有提前加载的组件,样式则全部不生效。
验证过程
首先带着疑问,先对属性的兼容性做了验证:
flex 属性验证
首先在局部注册组件中打印下面的信息,不出意外this.checkFlexSupport()
返回 true,并且 vw
属性也是可行。
activated() {
if (this.checkFlexSupport()) {
console.log('==============Flexbox is supported============');
} else {
console.log('===============Flexbox is NOT supported');
}
console.log(this.checkVwSupport(), '===============vw===============');
}
methods: {
checkFlexSupport() {
const testElement = document.createElement('div');
testElement.style.display = 'flex';
return testElement.style.display === 'flex';
},
checkVwSupport() {
const testElement = document.createElement('div');
testElement.style.width = '1vw';
return testElement.style.width;
},
}
float 布局验证
将 flex
布局改成 float
布局进行验证,并用getComputedStyle()打印元素的样式,结果元素的属性皆为初始值!
内联样式验证
到这里,那只能怀疑在 vue 组件中的style
标签内的样式根本就没作用上!!!
继续带着疑问,将局部样式改成内联样式写法,结果生效了!!!
想着只要把所有有问题的组件的样式都改成内联方式就能关闭这个任务了。但改了一部分,用户反馈有问题的界面还在持续增加,若真全这么改,人都麻了。
所以应该就是小米最新手机的读 CSS 文件有问题,但如果是这样,其他组件不应该也会有问题吗?
通过排查和总结,发现有问题的基本都是局部注册组件,而全局注册组件都是正常。
那么可以采用方法二,将组件全部进行全局注册。
另外是不是只要将 CSS 样式全部内联也可以?
研究打包结果发现 CSS 样式都被提取到了单独的 CSS 文件。那是不是可以不提取?
查看 Vue-CLI
配置可知,配置extract: false
可 将 CSS 样式动态注入到 JavaScript 中的 inline 代码中。
所以在 vue.config.js
中添加配置,并重新打包。打包的 dist 并没有生成独立的 CSS 文件,而是将 CSS 潜入 JS 中。
over~
扩展
Vue 的局部注册组件和全局注册组件的区别
特性 | 局部注册组件 | 全局注册组件 |
---|---|---|
加载时机 | 仅在某个父组件的 components选项中注册 | 在 Vue 实例中全局注册(如 app.component) |
使用范围 | 仅在当前组件及其子组件中使用 | 在整个应用中都可以使用 |
性能 | 只有需要的组件被加载,性能更优 | 可能导致不必要的内存占用和性能问题 |
命名冲突风险 | 组件名称不会与其他组件冲突 | 组件名需要唯一,可能存在命名冲突风险 |
代码组织 | 适合组件仅在局部使用,避免冗余 | 适合需要全局使用的组件,减少每次使用时的导入和注册 |
使用方式 | 需要在模板中通过 <component-name /> 来使用 | 直接在模板中使用,无需再次导入和注册 |
局部注册和全局注册组件加载时机对比
特性 | 局部注册组件 | 全局注册组件 |
---|---|---|
加载时机 | 在父组件实例化时加载,只有在父组件需要使用时才会加载 | 在 Vue 应用初始化时加载,应用生命周期内一直存在 |
资源占用 | 只在使用时加载,避免不必要的资源浪费 | 一开始就加载,可能会占用更多内存,尤其是未使用时 |
渲染时机 | 当父组件渲染时才渲染,只有当模板引用时才加载 | Vue 启动时就会注册并渲染 |
生命周期 | 组子组件的生命周期与父组件的渲染生命周期相关 | 组件生命周期在应用启动时就初始化,整个应用共享 |
Vue配置css.extract: false 的影响和优缺点
优点:
- 开发模式下更快的构建速度:
○ 在开发环境中,CSS 被注入到 JavaScript 文件中,避免了额外的文件生成和文件系统的 I/O 操作,因此可以提高开发时的构建速度。
○ 不会生成单独的.css
文件,减少了文件的处理和打包过程。 - 避免出现 CSS 文件丢失:
○ 如果你的项目比较小,或者只在浏览器内使用 JS 动态加载 CSS,extract: false
可以避免一些 CSS 文件在构建或部署过程中丢失的问题。
缺点:
- 生产环境性能下降:
○ 如果你在生产环境中使用css.extract: false
,CSS 将会与 JavaScript 一起打包。这样一来,页面加载时,浏览器需要下载和执行较大的 JS 文件,可能会导致初次加载速度变慢,影响用户体验。
○ 因为 CSS 是和 JS 文件一起加载的,所以浏览器无法单独缓存 CSS 文件。这意味着每次加载页面时都必须下载整个 JS 文件和 CSS,浪费带宽。 - 缺乏 CSS 文件的独立缓存:
○ 当 CSS 与 JavaScript 一起打包时,浏览器无法独立缓存 CSS 文件。即使你只更改了 JS 文件中的内容,CSS 也需要重新下载,因为它和 JS 文件捆绑在一起。
○ 如果项目较大或样式文件较多,这会导致不必要的网络流量。 - 影响代码分离:
○ 使用extract: false
可能导致代码分离不完全,从而影响应用的可维护性和优化。通常情况下,将 CSS 提取到单独的文件有助于减少 JavaScript 文件的大小,提高页面加载性能,尤其是对于长期缓存和按需加载非常重要。
总结:
● 开发环境:在开发模式下,使用 css.extract: false
是可以接受的,因为它可以提升构建速度,避免不必要的文件操作。
● 生产环境:在生产环境中,不建议使用 css.extract: false
,因为它会影响页面加载速度和缓存策略,增加网络请求的负担。推荐使用 css.extract: true
来将 CSS 提取为独立文件,从而提高性能。