记录篇(2)---- uniapp在项目中的实际问题

项目也总算正式上线了,终于有时间来记录这段时间在项目中的一些问题和不足了。

1.onLoad和onShow
onLoad: 页面加载的时候触发,只触发一次,从二级页面回来时不会触发。
onShow:页面显示的时候触发,只要进入或返回该页面就会触发,从二级页面回来也会触发。

例子:
第一次进入A页面,会依次触发onLoad和onShow方法,再进入B页面,从B页面返回到A页面时会触发onShow方法。

onSHow方法用来刷新页面比较合适,onLoad方法适合用在初始化加载数据时。
onLoad在onShow之前触发。
2.安卓应用加载网络图片,解决缓存不能正常更新图片的问题

图片是从服务器获取直接放在页面加载的,所以当页面加载之后图片也加载完成,但由于安卓应用会自动缓存加载过得图片,当服务器修改过同名的图片时,APP中并不会显示新的图片。这个问题一直困扰良久,后来想到一个方法就是直接给网络图片加一个时间戳,一秒更新一次,这样的话就不会出现缓存不显示正确图片的情况了,但这样做会导致另外的问题就是当网络不好或断网的情况下,图片不能显示…大家如果有更好的方法的话欢迎分享哟~

let now = new Date();
 // 创建时间戳 (由于计算出的是毫秒为单位的时间戳,请求时间过快,并不符合实际需求,所以转换为秒的时间戳就行)
let time = now.getTime()/1000; 
let img = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1575437545598&di=04d0f1f2dc5165ff441b66b0f6a38423&imgtype=0&src=http%3A%2F%2Fwx3.sinaimg.cn%2Forj360%2F005ZWRGigy1g7moazx0hnj30dw08qwfb.jpg?t=' + time
3.setInterval()和setTimeout()的区别

setInterval()和setTimeout()常被用来处理延时和定时任务。

setTimeout:用于在指定的毫秒数后调用函数或计算表达式。
setInterval:在每隔指定的毫秒数循环调用函数或表达式,直到clearInterval清除该定时器。

表达式:

setTimeout(()=>{
	// 逻辑代码
},1000)

setInterval(()=>{
	// 逻辑代码
},1000)

注:若只是想做延迟执行某方法或功能的话,建议使用setTimeout,尽量少使用setInterval。
可使用setInterval刷新表单,对于一些表单的假实时指定时间刷新同步。
如:

let timer = setInterval(() => {
	// 根据flag来判断是否暂定定时器
	if(this.flag) {
		// 从后台获取数据,更新数据
		uni.resquest({
			url: "",
			method: "",
			header: {},
			success: (res) => {
				this.data = res.data
			},
			fail: (err) => {
				console.log("请求失败:"+err)
			}
		})
	} else {
		// 使用clearInterval来结束该定时器
		clearInterval(timer)	
	}
}, 8000)

(每8秒执行一次任务,当this.flag为false是清除该定时器的任务)

以上是举的简单例子用来刷新后台给的数据,并没有判断状态码,也没有做性能优化方面的处理,请勿在项目中直接这样使用。

setInterval的弊端

(1)无视代码错误

对调用的代码是否报错并不会有其他提示,即使调用的代码由于某种原因出错,它还是会在没有碰到clearInterval的情况下
持续不断的调用该代码。

(2)无视网络延迟

由于某些原因(服务器过载、临时断网、流量剧增、用户带宽受限,等等),请求的实际时间会增加,但setInterval仍然
会按定时持续不断地触发请求,最终导致客户端网络队列会被塞满。
4.Math对象常用方法
// 1.只保留整数部分(丢弃小数部分)
parseInt(5.1234);// 5
// 2.向下取整(<= 该数值的最大整数)和parseInt()一样
Math.floor(5.1234);// 5    
// 3.向上取整(有小数,整数就+1)
Math.ceil(5.1234);

// 4.四舍五入(小数部分)
Math.round(5.1234);// 5
Math.round(5.6789);// 6
// 5.绝对值
Math.abs(-1);// 1
// 6.返回两者中的较大值
Math.max(1,2);// 2
// 7.返回两者中的较小值
Math.min(1,2);// 1
// 8.随机数(0-1)
Math.random();

// 解析字符串 返回浮点数 若不是数字 则返回NaN
parseFloat('5.1234'); // 5.1234
5.Date对象

Date对象具体的属性和方法请查看官方文档:点击此处查看官方文档

例子:获取当前时间的下周二14:00,若不足一天则使用倒计时,否则倒计天数。

// 使用面向对象 比直接使用时间戳要简单的多
getEndTime(globalCurrentDate) {
	// globalCurrentDate 是当前时间
	var now = new Date(globalCurrentDate);
	var nowTime = now.getTime();  // 获取当前时间戳
	this.currentTime = nowTime; 
	var endDate = new Date(); // 创建当前时间对象
	var day = now.getDay(); // 获取今天是周几
	var oneDayTime = 24 * 60 * 60 * 1000; // 一天的时间
	// 周天
	if (day == 0) {
		day = 7;
	}
	// 周一   获取结束对象
	if (day == 1) {
		// 周一的结束对象为当前时间(周一)+一天的时间
		endDate.setTime(nowTime + oneDayTime);
	} else if (day == 2) {  // 周二   获取结束对象
		// 周二的结束对象就是当前时间
		endDate.setTime(nowTime); 
		// 判断结束时间戳是否小于当前时间 若当前时大于结束时间 则为下个周二
		if (endDate.getTime() < nowTime) {
			endDate.setTime(nowTime + (9 - day) * oneDayTime);
		}
	} else if (day >= 3) { // 周三到周天则为正常的倒计天数 获取下周二的对象
		// 当前时间+ (9 - day) * 一天时间
		endDate.setTime(nowTime + (9 - day) * oneDayTime);
	}
	endDate.setHours(14, 0, 0, 0); // 下周二的结束时间
	let endTime = this.dateFormat(endDate, 'yyyy年MM月dd日'); // 将结束对象转为日期
	this.lastTime = endTime.split('年')[1]; // 周二的日期
	let days = (endDate.getTime() - nowTime) / oneDayTime; // 剩余天数
	if (days >= 1) {
		this.retaminDays = Math.ceil(days); // 向上取整获取剩余天数
	} else {
		this.continueTime((endDate.getTime() - nowTime) / 1000); // 24小时倒计时
	}
},
// 倒计时
continueTime(params) {
	// 根据params倒计时
	let timer = setInterval(() => {
		if (params > 0) {
			this.currentTime++;  //根据当前时间++
			params--;
			this.retaminDays = this.secToTime(params);
		} else {
			// 时间结束
			this.retaminDays = '00:00:00';
		}
	}, 1000);
},
// 将秒转为 时:分:秒
secToTime(time) {
	let t = '';
	if (time >= 0) {
		let hour = Math.floor(time / 60 / 60) % 60;
		let min = Math.floor(time / 60) % 60;
		let sec = time % 60;
		if (hour < 10) {
			t = '0';
		}
		t += hour + ':';
		if (min < 10) {
			t += '0';
		}
		t += min + ':';
		if (sec < 10) {
			t += '0';
		}
		t += sec;
	}
	return t;
},
// 获取截止日期
dateFormat(time, format) {
	var t = new Date(time);
	var tf = function(i) {
		return (i < 10 ? '0' : '') + i;
	};
	return format.replace(/yyyy|MM|dd|HH|mm|ss/g, function(a) {
		switch (a) {
			case 'yyyy':
				return tf(t.getFullYear());
				break;
			case 'MM':
				return tf(t.getMonth() + 1);
				break;
			case 'mm':
				return tf(t.getMinutes());
				break;
			case 'dd':
				return tf(t.getDate());
				break;
			case 'HH':
				return tf(t.getHours());
				break;
			case 'ss':
				return tf(t.getSeconds());
				break;
		}
	});
}

以上方法还可以简单一些,但是由于本人对时间实在掌握的不是很好,所以只能做到这里了。各位有意见可以提哦~~

6.eval()和JSON.parse() JSON.stringify()

(1)eval()
W3C中对eval()函数的解释是:可计算某个字符串,并执行其中的JavaScript代码。
示例:

eval("x=10;y=20;document.write(x*y)")  // 200
document.write(eval("2+2"))   // 4
var x=10
document.write(eval(x+17))   // 27

eval()还可以用来解析json
示例:

var data = "{a: '1',b: '2'}"
var obj = eval("("+data+")") // 转换为json
console.log(obj)    // {a:'1',b:'2'}

此处将data用()括起来是由于json是以”{}”的方式来开始以及结束的,在JS中,它会被当成一个语句块来处理,所以必须
强制性的将它转换成一种表达式。
 加上圆括号的目的是迫使eval函数在处理JavaScript代码的时候强制将括号内的表达式(expression)转化为对象,
 而不是作为语 句(statement)来执行。举一个例子,例如对象字面量{},如若不加外层的括号,那么eval会将大括号
 识别为JavaScript代码块的开始 和结束标记,那么{}将会被认为是执行了一句空语句。
 看下面两个例子:
 console.log(eval("{}"); // return undefined 
 console.log(eval("({})");// return object[Object] 

注:虽然 eval() 的功能非常强大,但在实际使用中用到它的情况并不多。
(2)JSON.parse() 和JSON.stringify()

前者是将格式完好的json字符串转为json对象,所谓“格式完好”,就是要求json字符串必须严格符合JSON格式,属性名和
属性值必须用双引号,单引号只能用在{}外。
后者是将json对象转为字符串,在获取后台返回的数据时,经常会使json对象的格式,若直接打印此对象会出现
object Object,所以此时只需要使用JSON.stringify()转换一下即可看出json对象的数据。

示例:

var jsonStr = '{"a":"1","b":"2"}';
var obj = {a:"1",b:"2"};
console.log(JSON.parse(jsonStr)) // {"a":"1","b":"2"}
console.log(JSON.stringify(obj)) // {"a":"1","b":"2"}(此类型为string)

注:若jsonStr中有单引号导致JSON格式不对时,可将单引号转为双引号即可:
'{'a':'1','b':'2'}'.replace(/\'/g,'"')
7.检测升级

APP升级是一个很有必要的功能,在本次项目中升级的思路是:
① 首先检测后台的版本号与当前项目的版本号是否相同,如果相同则不升级,反之提示升级。
② 如果需要强制升级的话,则会将所有用户的状态清除,即使用户此时还在APP中,也会被强制退出提示升级。

升级代码演示:

checkVersionClick() {
	var that = this
	uni.request({
	method:'GET',
	url:'http:/xxx.xxx/getVersion/',
	header: {
		'Content-Type': 'application/json',
		"Accept":"application/json",
	},
	success: (data) => {
		if(data.statusCode === 200){
			let version1 = plus.runtime.version
			let version2 = eval('(' + data.data[0].description + ')').versionNum
			if( version1 != version2){
				if(eval('(' + data.data[0].description + ')').isForceUpdate == 1){
					uni.showModal({ //提醒用户更新
						title: "更新"+eval('(' + data.data[0].description + ')').versionNum+'提示',
						confirmText:'立即升级',
						cancelText:'退出APP',
						showCancel:true,
						content: eval("(" + data.data[0].description + ")").description,
						success: (res) => {
							if (res.confirm) {
								that.isOnshowcheckVersion = true
								plus.runtime.openURL(eval('(' + data.data[0].description + ')').pkgUrl);
								// plus.runtime.restart();//下载后重启app
							}else if(res.cancel){
								uni.showModal({  
									title: '退出应用提示',  
									content: '是否退出大鲸智能?',  
									success: function(res) {  
										if (res.confirm) {  
											// 退出当前应用,改方法只在App中生效  
											plus.runtime.quit();
										}else{ 
											that.checkVersionClick()
											that.isOnshowcheckVersion = true
											
										}  
									}  
								  });  
							}
						}
					})
				}
				
			}
		}
	}
})
},

升级设计的一些功能均是使用plus 5+ 的api做的点击此处查看官网
5+的api用的不是很多,但是功能还是很强大的,有时间也需要多去研究研究哇。

8.uniapp打包

uniapp打包分为离线打包和在线打包。
离线打包即是使用Android studio以及官方SDK来进行打包,过程较为繁琐,有兴趣的同学可自行尝试点击此处查看详细过程
在线打包也叫云打包,过程简单,方便,推荐使用,具体过程如下:点击查看文档

① 安装JRE环境,自行百度查看安装过程

② 生成签名证书:进入cmd后输入
keytool -genkey -alias testalias -keyalg RSA -keysize 2048 -validity 36500 -keystore test.keystore
(testalias是证书别名,可修改为自己想设置的字符,建议使用英文字母和数字;test.keystore是证书文件名称,可修改为自己想设置的文件名称)
回车后输入需要填写的内容即可生成证书,记住此证书的路径。

③ 查看证书:keytool -list -v -keystore test.keystore 
输入密码后可看到证书的内容,此证书的MD5的指纹信息即为申请Andorid应用的应用签名,这两者必须匹配,否则上线可能会失败。

④ 在hx中点击发行-->原生APP-云打包-->填写包名,选择使用自有证书(此处的证书即为刚刚生成的证书),填写证书别名、私钥密码和文件路径。
渠道包是用于对应APP上线的应用商店,需要上线哪个应用商店就选择对应的渠道包。
若只是测试第三方SDK只需要点击自定义基座就可以了。

注:微信支付必须使用自定义基座,打包后才可以测试!!!

好哒~今天的总结先到这里了,之后有新的问题再更新啦,欢迎各位小可爱的留言哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值