解决方案:uni-app非nvue模式下切换主题后,App端闪屏、闪白、闪黑、状态栏主题色不稳定

uni-app主题色的BUG解决步骤给App添加主题色的缓存标识新建 __uniappview.html 文件引入 copy-webpack-plugin 依赖创建 vue.config.js 文件状态栏颜色不稳定结论主题切换采用的方案是 css 变量使用的编译版本是 3...

uni-app主题色的BUG

  • 解决步骤
    • 给App添加主题色的缓存标识
    • 新建 __uniappview.html 文件
    • 引入 copy-webpack-plugin 依赖
    • 创建 vue.config.js 文件
    • 状态栏颜色不稳定
  • 结论

  • 主题切换采用的方案是 css 变量
  • 使用的编译版本是 3.1.X (也就是HBuilderx的版本号)
  • 2.6.X 之后静止在js内动态引入css,所以这是一条死路

问题初探:
uni-app 使用非nvue模式进行编译App,会使用 web-view进行渲染。调试过程中发现,在进行加载静态资源的时候会首先读取默认的配置文件,并进行App主题的初始化,并且在加载其它页面的时候也会去重载默认的配置文件,然后再以加载我们正常的业务页面,在渲染业务页面之前的这段时间内,主题色会一直保持manifest.json内默认的配置色,或在main.js文件中预先加载的主题色。所以以这个思路去处理一下加载的静态文件,以处理切换主题色后闪屏的问题。

解决步骤

给App添加主题色的缓存标识

	plus.storage.setItem("theme", this.color)

这段代码是通过 HTML5+的Api,为App添加主题标识的缓存。

新建 __uniappview.html 文件

__uniappview.html 文件是uni-app App 模式的入口页,所以在这里修改比较合理

__uniappview.html 源文件:github

新建:__uniappview.html (建议放至 [ assets ] 目录下,默认是没有这个目录)

<!DOCTYPE html>
<html lang="zh-CN">

	<head>
		<meta charset="UTF-8" />
		<script>
			var __UniViewStartTime__ = Date.now();
			var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
				CSS.supports('top: constant(a)'))
			document.write(
				'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
				(coverSupport ? ', viewport-fit=cover' : '') + '" />')
		</script>
		<title>View</title>

		<script type="text/javascript">
			function PlusReady() {

				if (typeof PlusReady.instance === 'object') {
					return PlusReady.instance
				}

				// 获取app缓存的主题类型
				this.color = plus.storage.getItem('theme')
				this.cssPath = ''
				// 根节点,用于保存页面根样式,防止切换页面闪屏的样式
				this.style = document.createElement('style')
				this.link = document.createElement('link')
				// dom 是否更新过
				this.domStatus = false

				this.setTheme = function() {
					// 依据主题类型初始化主题相关值
					if (this.color == 'black') {
						plus.navigator.setStatusBarStyle('light') // 设置原生bar主题为浅色
						this.cssPath = "static/css/black.css" // 加载深色主题
						this.style.innerText =
							`
					        body, html, #app, page {
					          background: #1E1E1E !important;
					        }
					      ` // 设置根节点为深色,防止切换页面闪白
					} else {
						plus.navigator.setStatusBarStyle("dark") // 设置原生bar主题为深色
						this.cssPath = "static/css/white.css" // 加载浅色主题
						this.style.innerText =
							`
					        body, html, #app, page {
					          background: #FFFFFF !important;
					        }
					      ` // 设置根节点为浅色,防止切换页面闪黑
					}
					// 初始化link
					this.link.type = 'text/css';
					this.link.rel = 'stylesheet';
					this.link.href = this.cssPath;
				}

				this.pushHead = function() {
					// 节点载入head
					document.head.appendChild(this.link)
					document.head.appendChild(this.style)
				}

				return PlusReady.instance = this
			}
			function plusReadyTheme (str) {
				let plusReady = new PlusReady()
				plusReady.color = plus.storage.getItem("theme")
				plusReady.setTheme()
			}
			if (window.plus) {
				let plusReady = new PlusReady()
				plusReady.setTheme()
				plusReady.pushHead()
			} else {
				// h5+ 加载后,初始化参数并添加dom到head
				document.addEventListener('plusready', function() {
					let plusReady = new PlusReady()
					plusReady.setTheme()
					if (!plusReady.domStatus) {
						plusReady.pushHead()
					}
				}, false);
			}
		</script>
		<link rel="stylesheet" href="view.css" />
	</head>

	<body>
		<div id="app"></div>
		<script src="__uniappes6.js"></script>
		<script src="view.umd.min.js"></script>
		<script src="app-view.js"></script>
	</body>

</html>

在调试过程中发现,首先加载的是这个HTML,所以把设置主题色的代码放在了这个HTML
。这个HTML是在编译过程中导入的入口文件,每次离线打包后也可看到这个文件。

引入 copy-webpack-plugin 依赖

项目内使用的是:5.0.0 版本

	npm install -S copy-webpack-plugin

创建 vue.config.js 文件

const path = require('path')
const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = {
    configureWebpack: {
        plugins: [
            new CopyWebpackPlugin([
                {
                    from: path.join(__dirname, 'assets'), // 项目内把 __uniappview.html 文件放在了 assets 目录下
					force: true // 强制覆盖
                }
            ])
        ]
    }
}

状态栏颜色不稳定

这个问题也是默认配置的坑,初步观察的原理很简单,就是页面已经渲染出来了,但是又做了跳转当前页面动作、之类的动作,导致页面没有重新加载,但是配置重新加载了~ 所以uni-app的壳就把状态栏主题色恢复为默认了。
解决办法就是只要当前页面栈已经存在某个页面,就不做跳转之类的动作!

结论

以上方案,可解决闪屏问题,但是有一个小问题。就是在切换主题色后,切换的第一个页面还会闪一下。业务至此,接着搬下一块砖!!! 有更好的解决方案,或谁把这个遗留问题解决了下方评论,万分感激~

本文标题为:解决方案:uni-app非nvue模式下切换主题后,App端闪屏、闪白、闪黑、状态栏主题色不稳定

基础教程推荐