Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mobile开发经验沉淀 #2

Open
herbertliu opened this issue Dec 19, 2014 · 28 comments
Open

Mobile开发经验沉淀 #2

herbertliu opened this issue Dec 19, 2014 · 28 comments

Comments

@herbertliu
Copy link
Member

在手Q开发过程中,遇到各种问题,解决之后沉淀如下,细分为:

1、经验沉淀:开发过程怎么快速开发并在开发过程中可以兼顾到一些场景的出现
2、疑难问题:一些机型出现的疑难问题,如和解决,以及对应的机型等问题详细描述(截图)

@herbertliu herbertliu changed the title 手Q开发经验沉淀 Mobile开发经验沉淀 Dec 19, 2014
@webryan
Copy link
Member

webryan commented Dec 19, 2014

组织形式可以用问答的方式吧。 一个帖子逻辑扩展性比较差。

@herbertliu
Copy link
Member Author

@webryan 先在这里沉淀,多个帖子不太好找,可以在这里讨论,知识的整理在基于这里的沉淀。看讨论过程也是一中享受。而且这里有个好处可以看到历史的脚印。

@webryan
Copy link
Member

webryan commented Dec 19, 2014

@litten 这块知识体系没建立之前,先这么搞吧。 合理的方式应该是知识拓扑图和帖子、文章建立映射即可。

@herbertliu
Copy link
Member Author

IOS7白屏Bug

产生原因:IOS7中,如果html header 返回了cache-control:max-age=0(或者no-cache),这个时候Browser不会cache页面,但浏览器每次请求都会携带请求头(If-Modified-Since或者If-None-Match)。如果此时服务器刚好没有修改的话,会识别成304给Browser,此时前面已提到过Browser没有缓存页面内容,导致取不到页面而白屏。详细Bug描述猛戳这里

解决办法

  •  **设置cache时间(诸如:cache-control:max-age=600):**
     对于首页更新要求来讲,如果有cache的话,不利于首页及时更新,对于更新场景不多的情况,可以采取这个办法
    
  •  **去掉cache-control字段头(我们采取这个方案)**
    
  •  **服务器动态处理:**
    当然对于以上的方案都是基于IOS7,服务器根据请求的Header头中的User-agent来单独针对IOS7及以上处理
    

@litten
Copy link

litten commented Dec 19, 2014

@herbertliu 这块我感觉另开一个repository,用rm的形式沉淀性会更好,大家也更好修改和提交。
比如:
移动Web前端知识库
iOS与Android平台上问题列表

@herbertliu
Copy link
Member Author

@litten 他这个已经是总结的了,总结的是基于这个讨论梳理出来的。现有讨论沉淀,然后才有梳理。我们到时候梳理会形成知识图(形成repository)。主要是有些需要讨论的,可以在这里进行一个讨论。

@webryan
Copy link
Member

webryan commented Dec 19, 2014

md的确更适合展示,先沉淀到这里吧。后面会整理一下的。 发现at没了yuanyan,战斗力差了好多

@ousiri
Copy link
Contributor

ousiri commented Dec 22, 2014

Android2.3下transform失效

Android 2.3某些页面的transform失效, 导致rotate等属性无效, 可以通过user-scale=yes部分解决.

腾讯播放器使用时遇到的坑

  1. iOS下单页面里初始化多个video, 会出现神奇的bug. 因此不要初始化多个video
  2. 使用播放器+poster覆盖掉原来的图片(例如课程详情页), 会有一段时间的白屏. 解决方法是oninit并且延时100ms才把播放器展示出来.

@longyiyiyu
Copy link
Contributor

[经验沉淀]多页面更新

在移动端比较偏向于新开页面来处理一些事情,另外移动端的操作环境只有返回上一层和home两个操作,因此用户会经常回退到之前的页面,所以往往需要旧页面可以自动更新数据,而产品一般不会提到这些细节,所以需要开发自己保持这种习惯,不然会有很多这个bug和工作量留到测试阶段。目前有两种解决方案:

  • 高版本手Q(5.0)支持WebView的广播事件,可以通过这个进行数据更新,在手Q项目中,对于可以容忍低版本更新问题的可以采用这个方案
  • 利用localstorage进行页面之间的同步

@longyiyiyu
Copy link
Contributor

[机型兼容][IOS]type=search输入框会截取字符

是type=search的input的默认样式导致的:
image
解决办法是把默认样式去掉,或者添加padding-left或者text-indent

@longyiyiyu
Copy link
Contributor

[经验沉淀]tap点透问题

产生条件

如果绑定tap方法的dom元素在tap方法触发后会被干掉(隐藏,移走,删掉),则它底下同一位置的dom元素会触发click事件、或者有浏览器认为可以被点击有交互反应的dom元素(例如input的focus事件),这个称为“点透”现象。

产生原因

  1. click事件在移动端会有延迟(因为需要检测双击事件,移动端click300毫秒延迟的原因
  2. zepto的tap事件是绑定在document.body上的,tap事件执行(冒泡之后)之前,click事件已经被"执行",只是被延迟了而已,所以在tap事件用preventDefault也无济于事

解决方案

  1. 底下的元素也使用tap事件,即上下两个元素使用同一种事件(tap/click)
  2. 不要使用tap事件,使用touchend事件处理,并preventDefault掉(不优雅,而且暴力)
  3. 使用fastclick库,其实现原理就是把click的300ms延迟干掉

@longyiyiyu
Copy link
Contributor

[机型兼容][IOS]position:fixed + input问题

当input获得焦点并弹出虚拟键盘时,页面上position:fixed的元素的位置会错乱。

解决方案

  1. 用position:absolute模拟,这个效果不佳,在pc端hack ie6...只能呵呵
  2. 当input元素focus时,改成position:absolute,blur的时候再改回来
  3. 使用iscroll库
  4. 使用div内滚动

@longyiyiyu
Copy link
Contributor

[机型兼容][IOS8]闪屏问题

大面积的页面内刷新时出现,这种闪屏不是位置错乱的那种闪屏,具体原因不详

规避方案

  1. 提高刷新效率,尽量减少reflow和repaint
  2. 刷新之后不要改变页面的scroll状态,即不要从不能scroll刷到可以scroll,反之亦然(利用min-height让页面一直处于scroll状态,在用)
  3. 不要刷新图片,利用localstorage缓存图片链接,命中的图片直接使用src,而不要用lazyload(在用)

@longyiyiyu
Copy link
Contributor

[经验沉淀]别忘了点击态

就像pc端的3态,在移动端需要点击态,移动端的点击态实现是点击时添加一个active类,300ms后去掉,建议把点击态放到移动端视觉检查项中

@longyiyiyu
Copy link
Contributor

[经验沉淀]页面的各种状态

这些状态pc端也会用到,不过在移动端会更为需要,因为移动端网络延迟高并且不稳定。建议是把页面的各种状态抽象为组件,并整合在一个组件中统一管理会比较好,这个待优化,现总结页面中会出现的各种状态:

  1. 加载js前,需要在html内显示【正在加载】或其它类似标志
  2. 加载js后,调用cgi时,显示loading标志
  3. 如果cgi做了localstorage缓存,在展示local数据同时拉cgi时,显示更新数据标志
  4. 数据为空时,应该展示空标志(不管是cgi返回空结果,还是页面更新数据后变成空结果)
  5. cgi加载失败,显示重试提示,点击后可触发重试逻辑

@longyiyiyu
Copy link
Contributor

[经验沉淀]cgi添加localstorage逻辑之后需要注意的地方

  1. 变量重复初始化
  2. 事件重复绑定
  3. 页面状态切换

@longyiyiyu
Copy link
Contributor

[机型兼容][IOS 5+]快速回弹滚动问题

IOS5新特性webkit-overflow-scrolling: touch可以启动快速回弹滚动(fast bounce-scroll)效果,但是它会阻止渲染直到滚动结束。

影响

  1. 从不滚动状态到滚动状态(反之亦然),因为要先初始化滚动状态才开始渲染,虽然很短暂,但也是有delay的,所以出现闪屏(公众号2期课程详情页闪屏问题)
  2. 列表滚动过程中,需要等到滚动结束之后,后面的元素才会渲染出来(公众号2期课程列表页下拉刷新元素出来慢的问题)

解决方案

  1. 启动硬件加速,可以用-webkit-transform: translate3d(0,0,0),这个hack可以解决大部分问题
  2. 用min-height,直接杜绝滚动状态改变,从而防止闪屏问题(已解决详情页闪屏问题)

ps: 【[机型兼容][IOS8]闪屏问题】的根本原因

@ousiri
Copy link
Contributor

ousiri commented Jun 9, 2015

[机型兼容][iOS] 部分图片不缓存

经过排查, 图片大于1M的情况下, 并且开启了crossOrigin, 就会导致浏览器不缓存该图片.

解决方法是:

  1. 图片大小减少
  2. 去掉crossOrigin

@herbertliu
Copy link
Member Author

@ousiri 图片不缓存,有哪些机型有问题?

@ousiri
Copy link
Contributor

ousiri commented Jun 9, 2015

iOS~~~~

@haledeng
Copy link
Contributor

Listview 太长引起的手机性能问题

内存中存留的DOM结构太多,导致滚动的 Listview 后面,点击响应会延迟,甚至无响应。

解决方法是:

  1. 在 li 外面包裹一层,将前面页码的 dom 移除,同时设置外层容器的高度(这样不至于影响滚动条)
    2015-06-14 10 15 53

  2. 下拉滚动翻页过程中,对之前页码的数据进行隐藏。
    qq 20150618095357
    向上滚动时,采取一定的策略将隐藏的数据显示

            var $lastHidden = $teacherList.find('li[data-show="hidden"]').last(),
                lastHiddenPage = $lastHidden.data('page');
            var $midle = $teacherList.find('li[data-page="' + (lastHiddenPage + 2) + '"]').eq(4);
            if($midle && $midle.offset() && $midle.offset().top > $(document.body).scrollTop()){
                // 页面中最后一个元素显示在屏幕中
                // problem: 向上滑动过快,这里有卡顿
                $teacherList.find('li[data-page="' + lastHiddenPage + '"]').css('visibility', 'visible').data('show', 'visible');
            }
    

获取最后一个隐藏的元素,得到隐藏的页码,判断后2页中的第5条数据是否在屏幕中。

@coolriver
Copy link

弹出框中的滚动事件冒泡导致body也滚动

qq 20150731154952
如图所示,当弹出框内容在滚动时,如果滚动到边界,会导致页面内容也会跟着滚动。

  • _尝试解决但失败的方案_:
    (使用zepto)在弹出的对话框元素上捕获事件,并阻止冒泡(stopPropagation),虽然阻止冒泡后,在body上没有监测到touchmove事件,但是页面内容还是会被带着滚动。
  • 成功解决方案一
    在显示对话框时,将html和body的height都设置为100%,overflow都设置为hidden,然后在对话框关闭时将html和body的height与overflow属性都设置为auto。
    打开对话框和关闭对话框后分别执行的函数:
    function lockBody() {
        $body.css({
            height: "100%",
            overflow: "hidden"
        });

        $html.css({
            height: "100%",
            overflow: "hidden"
        });
    }

    function unlockBody() {
        $body.css({
            height: "auto",
            overflow: "auto"
        });
        $html.css({
            height: "auto",
            overflow: "auto"
        });
    }

这种方案最先想到,但这种方案比较麻烦,需要使用js在对话框显示与关闭时更改元素的css,性能会受影响。

  • 成功解决方案二
    在body内加一层div.scroll-wrapper,这个div包含页面的所有显示内容但不包含弹出框,.scroll-wrapper和html还有body的height都为100%,html和body的overflow为hidden,.scroll-wrapper的overflow为scroll。让.scroll-wrapper的div来控制页面内容的滚动。因为弹出框是通过fix布局不属于.scroll-wrapper的子元素,所以滚动不会冒泡到.scroll-wrapper上。
    DOM结构:
<body>
    <div class="scroll-wrapper">
        <div class="banner">
            banner
        </div>
        <div class="content">
            <p>p </p>
        </div>
    </div>
    <div id="mask">
    </div>
    <div class="dialog">
        <div class="dialog-head">

        </div>
        <div class="dialog-body">
            <ul>
                <li>aaaaaaaaa</li>
            </ul>
        </div>
        <div class="dialog-foot">
            <a href="javascript:;">确定</a>
            <a class="close" href="javascript:;">关闭</a>
        </div>
    </div>
    <script src="zepto.js" ></script>
    <script src="index.js" ></script>
</body>

CSS:

.scroll-wrapper {
    height: 100%;
    width: 100%;
    overflow: scroll;
}

html, body {
    height: 100%;
    overflow: hidden;
}

这种方法不需要使用js逻辑来控制,只用加一个div元素并设置相应的css进行控制。

测试源代码:https://github.com/coolriver/webTest/tree/master/mobileH5/dialogScroll

@chshouyu
Copy link

我是用的iscroll解决的上述问题

@herbertliu
Copy link
Member Author

@chshouyu iscroll模拟滚动,自然就不会有这个问题了,只是iscroll在很多android机型下有性能上的影响,而且在ios下不如原生的流畅,所以除非是必须要用iscroll(比如:需要监听滚动事件等),才会将原生滚动换成iscroll。

@banyaner
Copy link

这两种解决方案在ios上表现都不太好,ios上滚动没有惯性动画了啊。感觉这种方法搭配iscroll,根据操作系统选择使用的方法更好些?我最后用的也是iscroll

@herbertliu
Copy link
Member Author

@banyaner 在实际业务中,确实需要根据场景做一些不同的处理。比如说浮层的场景,整个dom的场景都不一样,根据场景不同。另外不同平台的考虑也需要。总之,方案有这些,需要不同场景选择合适的方案。

@Guocover
Copy link
Member

Android手Q的X5内核webview使用两个方向原生滚动会导致页面截断

如下图,页面存在这window的垂直滚动,和红色框的纵向滚动
image

红色框是使用原生的overflow-x:scroll
image

然后
向下滚动一部分页面,然后左右滚动红色区域的地方

image

接着向上拉,滚回原来的头部,,页面出现截断
image

@huoxudong125
Copy link

[疑难问题]IOS 中微信浏览器中滚动事件触发多次,导致数据重复加载。

   //滚动事件(安卓没有触发多次,IOS中一次滚动会触发多次事件)
        $(".contain").scroll(function () {

            if ($(this).scrollTop() + $(this).innerHeight() > $(this)[0].scrollHeight - 300
			&& mySpace.oldScrollHeight < $(this)[0].scrollHeight) {
				mySpace.oldScrollHeight=$(this)[0].scrollHeight;
                console.log(mySpace.currentTabId + " scroll to bottom");
                mySpace.getDataByTabId();
				//alert("scroll to bottom"+mySpace.oldScrollHeight);
            }
        });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests