在移动WEB开发中,经常会遇到页面内嵌入一个可滚动的滚动的区块的场景,在iOS safari中,由于页面有着弹性回滚的特性,若想阻止页面弹性回滚,通常做法是阻止touchstart的默认行为,但这样会导致页面内所有区块都无法滚动,通过以下代码可以实现选择性的弹性滚动。

JS部分:基于zetpo扩展

/**zepto 方法扩展*/
$.extend($.fn, {
    computedStyle: function (val) {
        if (this.length === 0 || val == undefined) return;
        return window.getComputedStyle(this[0], "")[val];
    }
});

/**
 * 阻止iOS中页面弹性回滚,只允许div.scroller的区块有弹性
 */
(function ($) {
    var selector = '.scroller'; //需要滚动区域的class选择器
    if ($.os.ios) {
        window.addEventListener("touchstart", handlePageBounce, false);
        window.addEventListener("touchmove", handlePageBounce, false);
    }
    function handlePageBounce(evt) {
        if (evt.type === "touchstart") {
            this._startTouchY = evt.touches[0].screenY;
            return;
        }
        var panel = $(evt.target).closest(selector);
        if (panel.length === 0) return evt.preventDefault();
        var el = panel.get(0);
        var canScroll = el.scrollHeight > el.clientHeight;
        var hasOverflow = $(el).computedStyle("overflowY") !== "hidden";
        var height = parseInt($(el).computedStyle("height"), 10);
        if (canScroll && hasOverflow) {
            var currY = evt.touches[0].screenY;
            var scrollAtTop = ((this._startTouchY <= currY) && (el.scrollTop === 0));
            var scrollAtBottom = ((this._startTouchY >= currY) && ((el.scrollHeight - el.scrollTop) === height));
            if (scrollAtTop || scrollAtBottom)
                evt.preventDefault();
        } else {
            evt.preventDefault();
        }
    }
})($);

CSS:

.scroller { overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; }

HTML:

<div class="scroller" style="height:100px;">
    <div>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
        内容。。。<br>
    </div>
</div>

凡是带有scroller样式的区块都有弹性回滚效果,可同时存在多个。