最近使用uni-app做了一个小程序的项目,有一个功能是把多个文件拍照并上传。
在使用过程中部分机型白屏会导致页面报错,图片丢失。我研究了一下,找到了解决办法。
下面我简化代码,展示一下此功能的过程
- DOM
<template>
<view>
<image :src="item" alt="" v-for="item in imgList" :key="item.id">
</view>
</template>
- data里面定义图片列表imgList
data(){
return{
imgList:[]
}
}
- 调用上传的接口,参数与返回值简写了
upload(params).then(res=>{
this.imgList.push(res)
})
代码很正常,但在部分机型下在拍完照片之后页面会白屏几秒,页面重新加载,导致控制台报错。错误是这样的
导致这种错误的原因是:在元素加载之前,JavaScript 中使用了 DOM 元素。而 DOM API 对于空白的对象引用返回 null。任何执行和处理 DOM 元素的 JS 代码,都应该在创建 DOM 元素之后执行。
现在我们知道了原因,就知道从哪里入手了。我们让DOM解析完成之后,再去执行js的操作,这就涉及到了事件循环。
首先,事件循环分为宏任务和微任务。
- 初始化页面的时候,执行宏任务,即script 脚本(整体代码),执行过程中,遇到微任务放入微任务队列,遇到宏任务,放到宏任务队列。
- script 脚本执行完成,开始执行微任务,清空微任务队列,然后执行宏任务,清空宏任务队列。之后开始进入下一次事件循环。
我们现在就清楚的知道,拍完照执行的js代码需要在script 脚本执行完成之后在执行,所以我们有两种方式可以解决。把代码放入微任务里执行或者放入宏任务里执行。
这里我采用的是放入宏任务里执行。在原代码基础上加个setTimeout。
upload(params).then(res=>{
setTimeout(()=>{
this.imgList.push(res)
})//不写时间,默认为0
})
知道原理之后,解决方法很简单。所以,重要的是分析产生问题的原因。
希望此文章能给到你帮助!