uniApp实现热更新的思路与详细过程

 更新时间:2022年11月11日 16:04:25   作者:碰磕  
经常在做app的时候,会有做热更新的需求,这也是常用的更新app的一种手段,下面这篇文章主要给大家介绍了关于uniApp实现热更新的思路与详细过程,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

热更新

热更新是开发中常见且常用的一种软件版本控制的方式,在uniapp进行使用热更新将软件实现更新操作
思路:

  • 服务器中存储着最新版本号,前端进行查询
  • 可以在首次进入应用时进行请求版本号进行一个匹对
  • 如果版本号一致则不提示,反之则提示进行更新执行更新操作

实现

采用方法封装进行使用~

1.封装一个对比版本号的函数

/**
 * 对比版本号,如需要,请自行修改判断规则
 * 支持比对	("3.0.0.0.0.1.0.1", "3.0.0.0.0.1")	("3.0.0.1", "3.0")	("3.1.1", "3.1.1.1") 之类的
 * @param {Object} v1
 * @param {Object} v2
 * v1 > v2 return 1
 * v1 < v2 return -1
 * v1 == v2 return 0
 */
function compare(v1 = '0', v2 = '0') {
	v1 = String(v1).split('.')
	v2 = String(v2).split('.')
	const minVersionLens = Math.min(v1.length, v2.length);

	let result = 0;
	for (let i = 0; i < minVersionLens; i++) {
		const curV1 = Number(v1[i])
		const curV2 = Number(v2[i])

		if (curV1 > curV2) {
			result = 1
			break;
		} else if (curV1 < curV2) {
			result = -1
			break;
		}
	}

	if (result === 0 && (v1.length !== v2.length)) {
		const v1BiggerThenv2 = v1.length > v2.length;
		const maxLensVersion = v1BiggerThenv2 ? v1 : v2;
		for (let i = minVersionLens; i < maxLensVersion.length; i++) {
			const curVersion = Number(maxLensVersion[i])
			if (curVersion > 0) {
				v1BiggerThenv2 ? result = 1 : result = -1
				break;
			}
		}
	}
	return result;
}

2.封装更新函数

通过downloadTask.onProgressUpdate进行监听,再通过plus.nativeUI.showWaiting("正在下载 - 0%"); 进行加载显示下载进度…

var updateUseModal = (packageInfo) => {
	const {
		title, // 标题
		contents, // 升级内容
		is_mandatory, // 是否强制更新
		url, // 安装包下载地址
		platform, // 安装包平台
		type // 安装包类型
	} = packageInfo;

	let isWGT = type === 'wgt'
	let isiOS = !isWGT ? platform.includes('iOS') : false;
	let confirmText = isiOS ? '立即跳转更新' : '立即下载更新'

	return uni.showModal({
		title,
		content: contents,
		showCancel: !is_mandatory,
		confirmText,
		success: res => {
			if (res.cancel) return;

			// 安装包下载
			if (isiOS) {
				plus.runtime.openURL(url);
				return;
			}
			let waiting =  plus.nativeUI.showWaiting("正在下载 - 0%");  
			// uni.showLoading({
			// 	title: '安装包下载中'
			// });
			// wgt 和 安卓下载更新
			const downloadTask = uni.downloadFile({
				url,
				success: res => {
					if (res.statusCode !== 200) {
						console.error('下载安装包失败', err);
						return;
					}
					// 下载好直接安装,下次启动生效
					plus.runtime.install(res.tempFilePath, {
						force: false
					}, () => {
						uni.hideLoading()
						if (is_mandatory) {
							//更新完重启app
							plus.runtime.restart();
							return;
						}
						uni.showModal({
							title: '安装成功是否重启?',
							success: res => {
								if (res.confirm) {
									//更新完重启app
									plus.runtime.restart();
								}
							}
						});
					}, err => {
						uni.hideLoading()
						uni.showModal({
							title: '更新失败',
							content: err.message,
							showCancel: false
						});
					});
				},
				//接口调用结束
				complete: ()=>{
					uni.hideLoading();
					downloadTask.offProgressUpdate();//取消监听加载进度
				}
			});
			//监听下载进度
			downloadTask.onProgressUpdate(res => {
				// state.percent = res.progress;
				waiting.setTitle("正在下载 - "+res.progress+"%");
				// console.log('下载进度百分比:' + res.progress); // 下载进度百分比
				// console.log('已经下载的数据长度:' + res.totalBytesWritten); // 已经下载的数据长度,单位 Bytes
				// console.log('预期需要下载的数据总长度:' + res.totalBytesExpectedToWrite); // 预期需要下载的数据总长度,单位 Bytes
			});
		}
	});
}

3.用变量接收实现函数(在函数中使用上方封装的函数)并导出

fRequestWithToken为我封装的请求方法,可自行进行使用axios进行请求也行!!!

var fCheckVersion = (cb) => {
	// #ifdef APP-PLUS
	plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {
		// console.log(widgetInfo.version)
		// console.log(plus.runtime.version)
		// console.log(widgetInfo.version)
		var nVerSta = compare(plus.runtime.version, widgetInfo.version),
			sLaststVer = plus.runtime.version;
		if (widgetInfo.version) {
			if (nVerSta == 1) {
				console.log(plus.runtime.version)
				sLaststVer = plus.runtime.version
			} else if (nVerSta == -1) {
				console.log(widgetInfo.version)
				sLaststVer = widgetInfo.version
			}
		}
		console.log(sLaststVer)
		//发送请求进行匹对,我这里数据库设定的是如果返回null则版本号一致,反之需要更新!!!
		fRequestWithToken({
			ajaxOpts: {
				url: URLS_COM.d_lastVer,
				data: {
					versionCode: sLaststVer
				}
			},
			showloading: false,
			silence:true
		}).then(data => {
			console.log(data)
			// console.log('################')
			if (data) {
				var sUrl = '',
					type = '';
				if (data.wgtName) {
					sUrl = data.wgtName;
					type = "wgt"
				} else {
					sUrl = data.pkgName;
					type = "pkg";
				}

				updateUseModal({
					title: data.title||"",
					contents: data.note||'',
					is_mandatory: true,
					url: sUrl,
					platform: 'android',
					type: type // 安装包类型
				})
			}
		}).catch((res)=>{
			cb&&cb()
			console.log(res)
		})
	})
	// #endif
}

export {
	fCheckVersion
}

以上代码即可实现热更新的操作

使用

可在App.vue中进行使用,根据项目需求而定

1.引入封装好的函数

路径自己记得填写自己封装的位置

import{fCheckVersion} from '@/common/project/checkversion.js'

2.然后可以在onLoad函数中进行触发

onLoad() {
		fCheckVersion();//检查更新
}

这样就实现了热更新

然后的话只需要进行打包个热更新的包

后端进行上传至服务器进行更新数据

本地再进行一个云打包,记得在mainifest.json文件中进行版本号的修改,修改成低于热更新包的版本号即可

补充:uniapp整包升级

整包升级代码:

在App.vue的onLaunch中,发起升级检测请求,如下:

onLaunch: function () {  
    //#ifdef APP-PLUS  
    var server = "https://www.example.com/update"; //检查更新地址  
    var req = { //升级检测数据  
        "appid": plus.runtime.appid,  
        "version": plus.runtime.version  
    };  
    uni.request({  
        url: server,  
        data: req,  
        success: (res) => {  
            if (res.statusCode == 200 && res.data.status === 1) {  
                uni.showModal({ //提醒用户更新  
                    title: "更新提示",  
                    content: res.data.note,  
                    success: (res) => {  
                        if (res.confirm) {  
                            plus.runtime.openURL(res.data.url);  
                        }  
                    }  
                })  
            }  
        }  
    })  
    //#endif  
}

注意:App的升级检测代码必须使用条件编译,否则在非App环境由于不存在plus相关API,将会报错。

升级地址URL,如果是自行托管的App,就提供自己的包地址。如果是打开应用市场,那URL如下:

if (plus.os.name=="Android") {  
    appurl = "market://details?id=io.dcloud.hellouniapp"; //这个是通用应用市场,如果想指定某个应用商店,需要单独查这个应用商店的包名或scheme及参数  
}  
else{  
    appurl = "itms-apps://itunes.apple.com/cn/app/hello-uni-app/id1417078253";  
}

总结

到此这篇关于uniApp实现热更新的文章就介绍到这了,更多相关uniApp实现热更新内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Javascript中的for in循环和hasOwnProperty结合使用

    Javascript中的for in循环和hasOwnProperty结合使用

    当检测某个对象是否拥有某个属性时,hasOwnProperty 是唯一可以完成这一任务的方法,在 for in 循环时,建议增加 hasOwnProperty 进行判断,可以有效避免扩展本地原型而引起的错误
    2013-06-06
  • Echarts横向堆叠柱状图和markLine实例详解

    Echarts横向堆叠柱状图和markLine实例详解

    一些柱形图在数据量比较多的时候,横向排列受到挤压,导致柱形图,变的非常细,影响整体的效果,所以应该将柱形图堆叠起来,这样就会好很多,下面这篇文章主要给大家介绍了关于Echarts横向堆叠柱状图和markLine的相关资料,需要的朋友可以参考下
    2022-06-06
  • JavaScript设计模式之抽象工厂模式介绍

    JavaScript设计模式之抽象工厂模式介绍

    这篇文章主要介绍了JavaScript设计模式之抽象工厂模式介绍,抽象工厂模式就是对功能类单独创建工厂类,这样就不必修改之前的代码,又扩展了功能,需要的朋友可以参考下
    2014-12-12
  • 基于javascript实现判断移动终端浏览器版本信息

    基于javascript实现判断移动终端浏览器版本信息

    这篇文章主要介绍了基于javascript实现判断移动终端浏览器版本信息,需要的朋友可以参考下
    2014-12-12
  • javascript 改变网页加载的CSS

    javascript 改变网页加载的CSS

    javascript 改变网页加载的CSS主要通过动态响应select触发的选项变化控制link标签加载的css,以实现不依赖cookie控制的页面css样式动态加载功能,需要的朋友可以参考一下
    2007-12-12
  • 使用postMesssage()实现跨域iframe页面间的信息传递方法

    使用postMesssage()实现跨域iframe页面间的信息传递方法

    下面小编就为大家带来一篇使用postMesssage()实现跨域iframe页面间的信息传递方法。小编觉得挺不错的,现在分享给大家,也给大家一个参考。一起跟随小编过来看看吧
    2016-03-03
  • 详解javascript常用工具类的封装

    详解javascript常用工具类的封装

    本篇文章主要给大家详细分析了javascript常用工具类的封装相关知识点,有兴趣的朋友参考下吧。
    2018-01-01
  • 微信小程序前端自定义分享的实现方法

    微信小程序前端自定义分享的实现方法

    这篇文章主要给大家介绍了关于微信小程序前端自定义分享的实现方法,文中通过示例代码介绍的非常详细,对大家学习或者使用微信小程序具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • 用JS控制回车事件的代码

    用JS控制回车事件的代码

    在写代码的时候偶尔会碰到被回车按钮所纠结的时候,例如上周客户反应我们的产品在页面按回车后,总是自动登出,而不是提交数据,客户对此也是意见很大。
    2011-02-02
  • JavaScript 函数用法详解【函数定义、参数、绑定、作用域、闭包等】

    JavaScript 函数用法详解【函数定义、参数、绑定、作用域、闭包等】

    这篇文章主要介绍了JavaScript 函数用法,结合实例形式分析了JavaScript函数定义、参数、绑定、作用域、闭包、回调函数、柯理化函数等相关概念、原理与操作注意事项,需要的朋友可以参考下
    2020-05-05

最新评论