H5开发

H5 开发实战记录(持续更新)

2017-08-27  本文已影响20人  风之化身呀

1、瀑布流

2、-webkit-overflow-scrolling : touch;
IOS下用这个属性可以实现流畅滑动,但要注意和这几个属性一起用

.container{
   -webkit-overflow-scrolling : touch; 
   overflow-y:auto;
    height:固定高度
}

如果.container有同级元素,且该元素用fixed定位,那么.container也必须使用定位属性,且设置z-index值,否则该属性可能不会生效。
注:Android下要实现类似流畅滑动,可尝试使用iScroll.js,地址在这

3、IOS下input问题

-webkit-tap-highlight-color: rgba(0,0,0,0);            //去除点击阴影,IOS私有
user-select:none;         //禁止用户选择文本
-webkit-touch-callout: none   //禁止图片长按弹出菜单,img和a标签都要加
pointer-events: none;            //禁止一切鼠标事件
-webkit-appearance: none;   //消除输入框和按钮的原生外观,在iOS上加上这个属性才能给按钮和输入框自定义样式 
// 实现谷歌浏览器支持<12px字体,比如显示7px,可采用如下方案
.test_tag{  
    font-size:12px;  
    -webkit-transform-origin-x: 0;  
    -webkit-transform: scale(0.5833333333333334);   //  7/12=0.5833
}  

5、使用content做一个三个点加载动画
本技巧来源于这里

<a href="javascript:" class="grebtn">订单提交中<dot>...</dot></a>
dot {
    display: inline-block; 
    height: 1em; line-height: 1;
    vertical-align: -.25em;
    overflow: hidden;
}
dot::before {
    display: block;
    content: '...\A..\A.';
    white-space: pre-wrap;
    animation: dot 3s infinite step-start both;
}
@keyframes dot {
    33% { transform: translateY(-2em); }
    66% { transform: translateY(-1em); }
}

原理:1 \A可以换行;2 before元素可以覆盖其寄生元素;3 用动画调整每次显示的content;4 不支持animation时只显示三个点(优雅降级&渐进增强)

6、奇怪bug

.hide{
   display:none;
}

假如你给一个元素A运用了.hide,那么当你移除.hide,想让A显示出来时,A会有一定概率显示不出来

7、事件代理是个好的事件处理技巧,但是要特别注意代理元素的选取,一般选取body,如果出现这种层级结构body>main>button,且main设置了opacity:1,那么想在body上代理button的点击事件是做不到的,因为body被main挡住了(PC端不会,但移动端会),解决方式是将代理设到main元素上,其实这个问题的根源在于opacity会挡住比他层级底的元素,使得事件冒泡无法进行。此外不要重复执行绑定操作,否则会被绑定多次(场景:A页面跳到B页面,在B页面做了修改A页面数据的操作,修改完返回到A页面,A页面需要重新拉数据渲染页面。这时应该只执行页面渲染操作,不能再执行事件绑定操作),浏览器对匿名函数的绑定会重复绑定,对命名函数的绑定不会多次绑定。

8、monitorEvents(dom,eventName),可以模拟某元素上所有事件


eventName可取值.png

9、webpack设置代理问题:


代理路径.png

不能把backend放在backend2前面,根源在于不能使用正则匹配,导致/backend2会被/backend代理。

10、正则
要写一个复杂的正则,不一定要写成一个完整的形式;还可以通过分布的形式来实现,比如

var hasNumberReg = /[0-9]/g,
      hasLetterReg = /[a-zA-Z]/g,
      hasSpecialReg = /[~!@#¥\$%\^&\*\(\)-_+=:;'",\.\<\>\/\|\\?\[\]{}]/g;
// 必须包含字母数字和特殊符号的密码,可以这样分步写
hasNumberReg.test(value) && hasLetterReg.test(value)&&hasSpecialReg.test(value)

11、image-set
image-set解决苹果的高平请显示图片问题,不支持image-set的浏览器下,他们解析background-image中的背景图像;
支持image-set:
如果你的浏览器支持image-set,而是普通屏下,此时浏览器选择image-set中1x背景图像
如果你的设备是高清屏幕下(ppi大于320时)时浏览器会选择image-set中@2x背景图像。

        仅支持background-image属性,而不能使用在'<img>'标签中,老的安卓4.4以下的不支持

        优点:image-set不需要告诉浏览器使用什么图像,而是直接提供了图像让浏览器选择
    selector{
        background-image:url(no-image-set.png);
        background:image-set(url(foo-lowres.png) 1x,url(foo-highres.png) 2x) center;
    }

12、移动端垂直居中问题(带四周边框)
为了兼容IOS和Android,可设置line-height比height少1-2个像素

13、REM布局
设置html的font-size时机要很早才不会有闪烁的感觉,直接在head里内联以下脚本即可,rem布局可能会产生小数像素问题,这会导致使用background-img时被裁掉一点,解决方案是设置background-img时注意留点空白,也就1px的事情,具体参看这里

<script>
(function(doc, win) {
    var docEl = doc.documentElement,
        resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
        recalc = function() {
            var clientWidth = docEl.clientWidth;
            if (!clientWidth) return;
            docEl.style.fontSize = clientWidth / 7.5 + 'px';
        };
    if (!doc.addEventListener) return;
    win.addEventListener(resizeEvt, recalc, false);
    recalc();
})(document, window);
    </script>

14、对于scroll事件或mousewheel事件,使用passive模式的监听器,可使滑动更顺畅。如何不择手段提升scroll事件的性能

window.addEventListeners('scroll',handler,{passive:true})
兼容性

15、DOMContentLoaded(蓝线),Loaded(红线),First Paint(绿线)


image.png

First Paint 一般位于二者之间,但最好在DOMContentLoaded之前
对于defer的js文件会在DOMContentLoaded之前执行。js执行期间与页面渲染是一个竞态,若js操作了dom,以往的渲染会被取消。这个问题在首屏的骨架屏需要注意

16、函数节流throttle和防抖debounce
节流:保证m时间内必定执行一次,如图片懒加载,不希望滑动停止时才开始加载,而是在滑动过程中就要开始加载
防抖:m时间内触发多次只执行一次,如scroll,resize等事件的触发

// 简单的节流函数
function throttle(func, wait, mustRun) {
    var timeout,
        startTime = new Date();
 
    return function() {
        var context = this,
            args = arguments,
            curTime = new Date();
 
        clearTimeout(timeout);
        // 如果达到了规定的触发时间间隔,触发 handler
        if(curTime - startTime >= mustRun){
            func.apply(context,args);
            startTime = curTime;
        // 没达到触发间隔,重新设定定时器
        }else{
            timeout = setTimeout(func, wait);
        }
    };
};
// 简单的防抖动函数
function debounce(func, wait) {
    // 定时器变量
    var timeout;
    return function() {
        // 每次触发 scroll handler 时先清除定时器
        clearTimeout(timeout);
        // 指定 xx ms 后触发真正想进行的操作 handler
        timeout = setTimeout(func, wait);
    };
};

17、webworker使用方式

// in html
<script type="text/javascript">
// we will use this function in-line in this page
function isPrime(number)
{
    if (number === 0 || number === 1) {
        return true;
    }
    var i;
    for (i = 2; i <= Math.sqrt(number); i++) {
        if (number % i === 0) {
            return false;
        }
    }
    return true;
}

// a large number, so that the computation time is sensible
var number = "1000001111111111";
// including the worker's code
var w = new Worker('webworkers.js');
// the callback for the worker to call
w.onmessage = function(e) {
    if (e.data) {
        alert(number + ' is prime. Now I\'ll try calculating without a web worker.');
        var result = isPrime(number);
        if (result) {
            alert('I am sure, it is prime. ');
        }
    } else {
        alert(number + ' is not prime.');
    }
};
// sending a message to the worker in order to start it
w.postMessage(number);

</script>
<p style="height: 200px; width: 400px; overflow: scroll;">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce blandit tristique risus, a rhoncus nisl posuere sed. Praesent vel risus turpis, et fermentum lectus. Ut lacinia nunc dui. Sed a velit orci. Maecenas quis diam neque. Vestibulum id arcu purus, quis cursus arcu. Etiam luctus, risus eu scelerisque scelerisque, sapien felis tincidunt ante, vel pellentesque eros nunc at magna. Nam tincidunt mattis velit ut condimentum. Vivamus ipsum ipsum, venenatis vitae placerat eu, convallis quis metus. Quisque tortor sapien, dapibus non vehicula quis, dapibus at purus. Nunc posuere, ligula sed facilisis sagittis, justo massa placerat nulla, nec pellentesque libero erat ut ligula. Aenean molestie, urna quis molestie auctor, lorem purus hendrerit nisi, vitae tincidunt metus massa et dolor. Sed leo velit, iaculis tristique elementum tincidunt, ornare et tellus. Quisque lacinia felis at est faucibus in facilisis dui consectetur. Phasellus sed ante id tortor pretium ornare. Aliquam ante justo, aliquam ut mollis semper, mattis sit amet urna. Pellentesque placerat, diam nec consectetur blandit, libero metus placerat massa, quis mattis metus metus nec lorem.
</p>

// in webworkers.js
function isPrime(number)
{
    if (number === 0 || number === 1) {
        return true;
    }
    var i;
    for (i = 2; i <= Math.sqrt(number); i++) {
        if (number % i === 0) {
            return false;
        }
    }
    return true;
}

// this is the point of entry for the workers
onmessage = function(e) {
    // you can support different messages by checking the e.data value
    number = e.data;
    result = isPrime(number);
    // calling back the main thread
    postMessage(result);
};

18、requestAnimationFrame提升滚动动画

const newScrollTop = this.getPosition(this.panes[index].$refs.content).top - this.distance

function scrollStep() {
    document.documentElement.scrollTop += 5
    if (document.documentElement.scrollTop < newScrollTop) {
        window.requestAnimationFrame(scrollStep)
    }
}
window.requestAnimationFrame(scrollStep)

可以将requestAnimationFrame看做一个钩子,刚好卡在浏览器重绘前向我们的操作伸出橄榄枝。实际上它更像定时器,每秒60次执行回调——符合屏幕的刷新频率,遇到耗时长的操作,这个数字会降到30来保证稳定的帧数。

19、做弹窗时,会涉及到z-index问题,最好将弹窗的div层级与主内容并列

上一篇下一篇

猜你喜欢

热点阅读