定制小程序:全局修改tabbar,导航栏主题色,闪烁问题

背景

由于公司为合作伙伴推出定制小程序服务,小程序都是一套代码实现,而每个小程序都有自己的导航栏主题色,自己的tabBar。

实现过程

查看官方文档,发现可以通过api来更改导航栏颜色,tabBar颜色,图标(下面称为主题)。

导航栏

js 复制代码
wx.setNavigationBarColor({
  frontColor: '#ffffff',
  backgroundColor: '#ff0000'
})

tabBar

js 复制代码
wx.setTabBarStyle({
  color: '#FF0000',
  selectedColor: '#00FF00',
  backgroundColor: '#0000FF',
  borderStyle: 'white'
})

开始实现

想法与实现1

是在app初始化的时候根据appId调用以上api设置不同的主题,调式后发现只能更改当前页面主题,跳转到另一个页面还是保留了app.json的主题设置。只能抽离设置主题方法,每个页面都调用一次。

但是这种方式有个体验问题,进入小程序是会先展示app.json里面的配置主题,再变回需要设置的主题,中间存在闪烁过程,从一个页面跳转到另一个页面也存在这个闪烁过程。体验非常不好。

想法与实现2

通过自定义导航栏和tabBar实现;一顿倒腾时候发现也是存在闪烁问题,小程序从加载到读取到自定义配置需要时间。

社区

查看社区,发现已经有非常多开发者提出了(全局修改主题和闪烁问题),但从19年到现在,依然没用合适的解决方法,官方也没有解决。

建议setNavigationBarColor加一个参数,使其能全局生效?

官方来看看,提个需求,希望wx.setNavigationBarColor增加设置全局导航栏颜色?

wx.setNavigationBarColor为什么不能全局生效

自定义tabbar切换时会闪烁

转换实现思路

看起来在小程序运行时更改配置的实现方式都体验不佳(闪烁);既然小程序读取的是先读取的是app.json的配置,那么可以考虑先更改小程序的app.json再进行打包上传预览;把修改主题的时机从小程序加载提前到打包环节。

下面的实现以我前几天的文章为基础进行修改,可先阅读这个:

微信小程序自动化部署miniprogram-ci,一套代码一键上传多个小程序

主要目录结构

  • 新建appConfig目录,存放各个小程序的主题(app.json里的window和tabBar)
  • 新建setAppConfig.js文件, 用于打包前更改app.json文件。
  • ci.js文件:循环执行所有app的打包预览,上传脚本

appConfig下的json文件结构

取自app.json里的部分配置,根据自己的定制需求增减。

setAppConfig.js脚本

作用为更改app.json里的部分配置,打包上传前执行。

  • 获取所有小程序配置文件
  • 根据传入的appId找到当前的配置文件
  • 读取app.json文件和当前app的配置文件,将配置文件主题写入到当前app.json
js 复制代码
const fs = require('fs');
const path = require('path')
const projectPath = path.resolve(__dirname, '..')
// app.json路径
const appJsonFile = `${projectPath}/app.json`
// 获取所有小程序上传密钥文件
const appConfigList = fs.readdirSync(`${projectPath}/ci/appConfig`)
// setAppConfig 将app.json更改成当前app的主题配置
const setAppConfig = (appId) => {
  let err = null
  try {
    // 根据appId找到当前的配置文件
    let jsonFileName = appConfigList.find(item => item.includes(appId))
    const appConfigFile = `${projectPath}/ci/appConfig/${jsonFileName}`
    // 读取app.json文件和当前app的主题配置文件,将主题写入到当前app.json
    let appJsonData = JSON.parse(fs.readFileSync(appJsonFile, {encoding: 'utf-8'}))
    const {window, tabBar} = JSON.parse(fs.readFileSync(appConfigFile, {encoding: 'utf-8'}))
    appJsonData.window = window
    appJsonData.tabBar = tabBar
    fs.writeFileSync(appJsonFile, JSON.stringify(appJsonData, null, '\t'))
  } catch (err) {
    err = err
    console.log(err)
  }
  return err
}
module.exports = setAppConfig

调整ci.js 上传与预览脚本

文件由前面的批量预览和上传脚本更改而来;批量预览和上传参考:微信小程序自动化部署miniprogram-ci,一套代码一键上传多个小程序

  • 获取所有小程序上传密钥文件
  • 根据上传密钥文件列表,获取appId列表
  • app.json先更改为第一个app的配置,根据命令进行预览/上传
  • 待执行完成后,再执行appId列表下一个app,直到最后一个
js 复制代码
// 使用ci脚本上传,需在小程序后台:开发管理 =》 小程序代码上传,生成小程序代码密钥放到privateKey文件夹;配置上传机器的IP白名单;上传前先预览再上传 npm run preview => npm run upload
const fs = require('fs');
const ci = require('miniprogram-ci')
const path = require('path')
const projectPath = path.resolve(__dirname, '..')
// 更改app.json js
const setAppConfig = require(`${projectPath}/ci/setAppConfig.js`)
// 获取所有小程序上传密钥文件
const privateList = fs.readdirSync(`${projectPath}/ci/privateKey`)
// 处理命令
const command = process.argv.slice(2)[0]
// 当前处理的第几个小程序
let appIndex = 0
// appId列表
let appIdList = privateList.map(item => {
  return item.split('.')[1] // item: private.appId.key
})
const uploadInfo = {
  version: '5.0.9',
  desc: '功能优化与修复bug'
}
// 处理上传和预览
let commandHandler = async () => {
  let appId = appIdList[appIndex]
  // 创建项目对象
  const project = new ci.Project({
    appid: appId,    // 小程序appid
    type: 'miniProgram',  // 类型,小程序或小游戏
    projectPath: projectPath, // 项目路径
    privateKeyPath: `${projectPath}/ci/privateKey/${privateList[appIndex]}`,  // 密钥路径
    ignores: ['node_modules/**/*']  // 忽略的文件
  })
  // 预览和上传前设置app json文件
  setAppConfig(appIdList[appIndex])
  if (command === 'upload') {
    await ci.upload({
      project,
      ...uploadInfo,
      setting: {
        es6: true, // 对应小程序开发者工具的 "es6 转 es5"
        es7: true, // 对应小程序开发者工具的 "增强编译"
        minify: true  // 是否压缩代码
      },
      onProgressUpdate: getstate,
    })
  } else if (command === 'preview') {
    await ci.preview({
      project,
      desc: '功能优化', // 此备注将显示在"小程序助手"开发版列表中
      setting: {
        es6: true, // 对应小程序开发者工具的 "es6 转 es5"
        es7: true, // 对应小程序开发者工具的 "增强编译"
      },
      qrcodeFormat: 'image',
      qrcodeOutputDest: `${projectPath}/ci/qrcode/${appId}_qrcode.jpg`,
      onProgressUpdate: getstate,
    })
  }
  // 监听上传过程,如果上传完成延迟一下再上传下一个,避免配置串了
	function getstate(e) {
		if (e._status == "done" && e._msg == "upload") {
			console.log(`${appIdList[appIndex]}--上传完成`)
      // 继续下一个,直到最后一个
      if (appIndex < appIdList.length - 1) {
        setTimeout(() => {
          appIndex += 1
          commandHandler()
        }, 1000)
      }
		}
	}
}
commandHandler()
相关推荐
小曲曲1 小时前
接口上传视频和oss直传视频到阿里云组件
javascript·阿里云·音视频
学不会•2 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
EasyNTS3 小时前
H.264/H.265播放器EasyPlayer.js视频流媒体播放器关于websocket1006的异常断连
javascript·h.265·h.264
井眼3 小时前
微信小程序-prettier 格式化
微信小程序·小程序
活宝小娜4 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点4 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow4 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o4 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
刚刚好ā5 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
qq_17448285756 小时前
springboot基于微信小程序的旧衣回收系统的设计与实现
spring boot·后端·微信小程序