Skip to content

背景:最近公司在优化二类户的代码,其中有一个很重要的流程就是影像上传,客户在开户的过程中需要上传影像资料(给身份证正反面拍照或选择本地图片的方式)因为用户可能在口袋内上传或者在 h5 页面操作,在口袋内上传就用aladdin的方式,使用OCR上传,但是在 h5 时候就使用原生的 input 上传影像,监听它的 change 事件,监听值改变后做处理。

本次优化的一项就是把影像上传这一部分抽成 VUE 组件,所以重构的时候就遇到了以下的BUG

  • 因为抽成了组件,所以上传身份证正反面的时候需要引两次组件。这个组件有两个选项,手机拍照选择本地图片 当同时选择拍照的 或者同时选择两张一样的图片时候 第二次上传并不会生效。
  • 因为我们的input 是 动态生成,在 移动端的时候选择上传图片并没有生效。

考虑:第二次上传没有生效 原因可能是 input 没有监听到 change 事件,那为什么第一次有效,第二次没有生效的原因是什么。当input 在本地选择同一张照片的时候,第二次 change 事件没有更新,原因比较简单,因为只有在 input 的值发生改变的时候才 change 事件才会触发,当用户第二次选择的图片和第一次选择的图片一样的时候, js 判断 两次的改变相同,也就是说 js 并不会觉得你第二次发生 change 了,栗子如下 :

javascript
var input = document.querySelector('input[type="file"]');
input.addEventListener('change',function(){
	console.log('被改变了')
	})

上面的例子如果选择同一张图片,第二次是不会有 console 的,那么如何让两次的操作都一样 也都能 触发 change 事件 呢?加上以下代码就好了

javascript
var input = document.querySelector('input');
input.addEventListener('change',function(event){
	console.log('被改变了')
	event.target.value = ''
	})

那为什么拍照的时候 也不能区分 change 事件呢,我有一个大胆的猜想,就是 系统不会知道你拍照的时候是拍的什么,因为你两次调用的拍照,那么就索性认定为操作为同一个对象,所以第二次就不会出发 change 事件了。

现在来看看第二个问题,移动端选择照片没有生效,后来经过排查,发现这是 safari 的兼容问题,也就是动态生成元素,且没有生成 DOM 节点时 并且是用click 模拟触发事件,发现 change 事件并不会生效 ,以下是我们刚开始的代码。

html
	<button id="btn">点击触发input change 事件</button>
	<script>
		var demo = document.querySelector('#demo');
		btn.addEventListener('click',function(){
			var btn = document.createElement('input');
			btn.setAttribute('type','file')
			
			btn.addEventListener('change',function(){
				alert('changed')
			})
		btn.click()
		})

	</script>

这段代码在 chrome 里可以正常运行,但是在移动端里无法弹出alert,后来我们在动态创建 input 改成 直接在DOM中生成。

总结:对于 DOM 事件还是不太熟悉,经验太少!