// 为何叫《大事记》?css
// 之前总有面试官问这样一个问题:“你在项目中遇到过最头疼的问题是什么,是怎么解决的?”node
// 当时总以为,已解决的问题都算不上头疼,因此回答老是不尽人意。web
// 最近遇到微信端的这个问题,很是让人头疼,正好有小伙伴和我聊到面试经验,灵机一动,《大事记》由此而生面试
问题描述:后端
在安卓系统的微信浏览器里面, 标签触发了 play() 事件,即开始播放以后浏览器
标签的层级会变成 MAX 级别,不管如何设置 z-index,都会遮挡别的脱离文档流的元素微信
分析缘由:app
微信的 X5 内核为了统一 在不一样的手机上的呈现形式,对 进行了改造ide
这样的改造在 IOS 系统上一切正常,但在安卓系统就会有各类问题,好比这里的层级过高工具
解决方案:
当测试的同事将这个 bug 提给个人时候,我根本没想到,我即将面对一场苦不堪言的角斗
第一回合:隐藏 video
最初暴露的问题并非页面底部的按钮,而是一个弹窗
在了解了问题的缘由以后,我当时的思路是:
打开弹窗的时候,将 标签隐藏掉,关闭弹窗的时候再显示
隐藏标签的方法有不少:display:none; visibility: hidden; z-index: -1; left: -9999px; opacity: 0;
但 display:none 没有占位,visibility 和 z-index 不起做用,opacity 虽然不显示元素,但依旧点不到下面的元素
因此只有用定位的办法了
let tag = document.createElement('style')
tag.id=id
tag.innerHTML= `video { position: relative; left: -9999; }`
body.appendChild(tag)
在打开弹窗的时候,经过上面的代码添加一个带有特殊 id 的
为了防止多级弹窗的时候重复建立
想通了这一系列逻辑以后,我猛然发现,页面底部的按钮也会被遮挡!
第二回合:跳转到单独页面播放
深思熟虑以后,我得出结论:遮挡问题无解
但问题仍是要解决,因而我向 PM 提出,单独写一个播放页面,点击 的时候跳转到这个页面进行播放
通过一番唇枪舌剑的交锋,PM 妥协了,但要求尽可能优化体验,打开的播放页看起来要像全屏播放同样
“这都不是事儿!” 我如是回道
播放页面确实不是事儿,可 真不是省油的灯
我本来想的是,全局添加一个 addEventListener('click'),若是点击的是 标签,就保存视频信息,并跳转到播放页面
document.addEventListener('click', (e) =>{
let target=e.targetif (target.nodeName.toUpperCase() === 'VIDEO') {this.setVideoUrl({
url: target.src,
poster: target.poster
})this.$router.push(`/video`)
}
})
这下跳转是没问题了,但在点击的时候,实际上还触发了 的 play() 事件
从理论上来讲,已经跳转页面了,这个 play() 事件并不须要阻止,但为了逻辑严谨,我仍是作了尝试
e.preventdefault()
e.stopPropagation()
e.cancelBubble()return false
然而这并不能阻止播放事件 play()
那就不阻止了
而后又了新的 Bug:部分机型从播放返回以后, 是播放的状态,并且有层级问题
第三回合:禁用 controls
我从新回到那个问题:如何阻止播放事件?
稍做挣扎,我就换了一个思路:若是没有播放按钮,那就不须要阻止播放事件了
因而我给 添加了 controls=""
这样就没有播放工具栏,以后只须要手动添加一个三角形的播放图标,一切就完美了
页面上的 是做为描述内容的一部分,包含在一段富文本里面,从后端返回的
这样一来, 相关的 DOM 节点只能经过 JS 修改,成本过高,因此我打算只用 CSS 来解决播放图标的问题
而后我画了一个播放的图标,给 添加了一个伪元素 :before,在伪元素里写好了样式,但毫无做用
原来 并不支持伪元素
“若是没法解决问题,那就让问题不存在”
我脑海中闪过这段话,而后有了新的方案:
我又画了一张图,而后将 的 poster 改为了这张图,问题解决了!
而后产品小姐姐跑过来:你对个人视频封面图作了什么?
决战:js 王道
既然 poster 不能改,那就只有经过 js 去操做 DOM,给 添加一个兄弟节点 做为播放按钮
而后将 和播放按钮一块儿包在一个容器
setVideoWrapper () {this.$nextTick(() =>{
let v= document.getElementsByTagName('video')if (v && v[0]) {//产品规定 页面中只会有一个
let target = v[0]//防止重复建立 wrapper
if (target.parentNode.className === 'video-wrapper') return
//清除 播放工具栏
target.controls = ''target.className= 'video-hack'
//建立播放按钮
let btn = document.createElement('i')
btn.className= 'video-play_btn'
//建立容器
let wrap = document.createElement('div')
wrap.className= 'video-wrapper'wrap.appendChild(btn)
wrap.appendChild(target.cloneNode())//插入容器并删除本来的
target.parentNode.insertBefore(wrap, target)
target.parentNode.removeChild(target)
}
})
}
再添加对应的 LESS 样式:
.video{&-wrapper {
position:relative;font-size:0;
}&-play{&_btn {
position:absolute;top:0;left:0;right:0;bottom:0;background:rgba(0, 0, 0, .1) url('img/url') center/80px 80px no-repeat;
}}
}
终于, 的问题完全解决了,皆大欢喜,普天同庆
但我仍是要吐槽一下,微信 的问题由来已久,开发团队也曾经说过要解决,但最后都不了了之
这大约都是时辰的错