解决移动端一像素问题的Vue指令

最近公司项目要解决一像素问题,本身琢磨了一阵子而且网上搜索了一堆博客,总结出最好的办法应该是经过css的transform scale缩放1px的内容来模拟设备上1px的效果了。可是这个方法有太多局限。而后秉着css解决不了的问题就用js来解决的原则,而后结合vue的自定义指令,手撸了一个一像素vue自定义指令。打算扔到giuhub留存。顺便总结一下遇到的问题。css

项目地址:https://github.com/HelloWorld20/onepxhtml

欢迎各位取用。若有错误的地方,也欢迎指正。vue

缘由

众所周知,自从iPhone 4带来了Retina display后,移动端开始引入了一个叫设备像素比(devicePixelRatio)的东西。git

另外一方面,若是给一个html标签写一个小于1px(H5)的border;IOS能够正常渲染,可是安卓设备不渲染。因此是不能用正常的方法来让安卓设备渲染一个1物理像素的线。github

戳这里看DEMO;web

固然用移动端才能看到效果:segmentfault

qrcode

网上的解决方案

网上搜能搜出不少解决方案,这篇文章基本汇总了网上的全部方案。而后结论是:使用css的伪元素来渲染一个1px(H5)的div,而且使用CSS3的scale来缩放dpr倍,从而渲染一个1px物理像素的线。dom

然而理论毕竟理论,用到项目中的时候仍是遇到了不少问题wordpress

1. 若是两个伪元素都被占用,则没法实现

网上的方案都是用CSS伪元素来实现的,而伪元素只有before和after两个,因此要是实际开发中中占用了before、after,则没法用CSS来实现模拟一像素。spa

2. 必须手动设置圆角

圆角是最头疼的问题。用CSS伪元素虽然能够作到圆角,可是CSS伪元素只能经过border-radius: inherit获得和父元素同样值的圆角大小,缩放以后就不同了,且css没法计算缩放后还和父元素同样的圆角。并且js也不能操做CSS伪元素,因此不得不手动计算dpr,而后给CSS伪元素设置圆角。

3. -webkit-device-pixel-ratio不是标准方法

MDN

CSS中判断设备设备像素比的方法是-webkit-device-pixel-ratio,不是标准的方法,因此用起来心慌慌。而JS的window.devicePixelRatio已经全面支持,顶多也就一个undefined。彻底不用担忧兼容性问题。

4. 部分标签不能设置伪元素

type为text的input标签就没法在标签内插入的dom(虽然控制台里显示已经被插入,可是不会被渲染出来),因此伪元素也没法给其加上模拟的1像素。

some text you can't see

更好的方案

本着CSS解决不了的问题就用JS来解决的思想。再结合Vue提供的自定义指令,能够在想要加1像素的html标签上加上一个指令,js能经过Vue的自定义指令拿到对应的DOM,那么就一切皆有可能。

最终实现了一个Vue指令,只须要给对应的HTML标签加上一条指令就行。其余的Vue指令自动处理。而且这个指令在咱们项目中运行过一段时间,基本是可靠的。

要注意的地方

  • 绑定的元素必须显示声明其position值为:relative、fixed、absolute之一,否则模拟一像素的div没法定位到位置
  • 务必给对应的DOM清除掉border样式
  • 不能用于<input type="text" />标签等内部不能插入元素的标签
相关文章
相关标签/搜索