每天一剂 WebView 良药

简介: 标签类Web App 建议用的样式用于覆盖 WebView 默认的样式,使得 App 看起来更像原生的 App,——“不露出马脚”/*document.documentElement.style.

标签类

  1. Web App 建议用的样式

    用于覆盖 WebView 默认的样式,使得 App 看起来更像原生的 App,——“不露出马脚”

    /*
    document.documentElement.style.webkitTouchCallout ='none'; //禁止弹出菜单
    document.documentElement.style.webkitUserSelect = 'none';//禁止选中 
    */
    body{
    	-webkit-text-size-adjust:none;	/* 字型大小是不會變的,而使用者就無法透過縮放網頁來達成放大字型 */
    	-webkit-appearance: none;		/*可以改变按钮或者其它控件看起来类似本地的控件*/
    	-webkit-user-drag: none; 		/*-webkit-user-drag CSS 属性控制能否将元素作为一个整体拖动。*/
    }
    a{
    	-webkit-tap-highlight-color: rgba(0, 0, 0, 0); /*很多Android 浏览器的 a 链接有边框,这里取消它 transparent */
    }
    /* For WebApp */
    body{  
      -webkit-user-select : none; /* 如果用户长按web网页的文本内容,都会出现选中的行为,提供复制文字等功能。禁止用户选中文字 for iOS */
    } 
    a, img{  
      -webkit-touch-callout:none;  /* 在IOS浏览器里面,假如用户长按a标签,都会出现默认的弹出菜单事件。禁止用户在新窗口打开页面、如何禁止用户保存图片\复制图片 for iOS */  
    } 

  2. 固定页面宽度

    <meta name="viewport" content="width=320,user-scalable=0" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/> 
    
  3. 触控面积

    请保证将每条数据都放在一个 a 标签中,并设置其 display: block;,为何这样做?因为在触控手机上,为提升用户体验,尽可能的保证用户的可点击区域较大。

  4. 调用手机拨电话面板、短信面板

    <a href="tel:18005555555">Call us at 1-800-555-5555</a>  
    
    <a href="sms:18005555555">
    <a href="sms:18005555555,18005555556">              
    <a href="sms:18005555555?body="> //大都不支持body参数

    安卓新系统支持程度都比较高,遗憾的是 iOS 新版反而不如旧版(旧版采用另外一种写法可以既支持号码又支持内容),详见下图:

  5. 去除 Android 平台中对手机、邮箱地址的识别

    <meta content="email=no"     name="format-detection" />
    <meta content="telephone=no" name="format-detection" />
    
  6. 如何禁止用户旋转设备

    iOS已经禁止开发者阻止 orientationchange 事件,那 Android 呢?对不起,我没有找到任何资料说 Android 禁止开发者阻止浏览器 orientationchange 事件,但是在 Android 平台,确实也是阻止不了的。

  7. 如何关闭 iOS 中键盘自动大写

    当虚拟键盘弹出时,默认情况下键盘是开启首字母大写的功能的,根据某些业务场景,可能我们需要关闭这个功能,移动版本 webkit 为 input 元素提供了 autocapitalize 属性,通过指定 autocapitalize=”off” 来关闭键盘默认首字母大写。

    另,设置是否使用输入的自动更正、自动不全、英文自动首字母大写。

    <meta content="email=no"     name="format-detection" />
    <meta content="telephone=no" name="format-detection" />
    
  8. IE8 CSS Selector

    IE8 虽然提供 CSS Selector 的 querySelector()/querySelectorAll(),但搜索不了自定义标签,不过你可以用*[attrib=value]搜索,但效率较低。

  9. 检测是否视网屏幕

    window.devicePixelRatio
  10. 浏览器是否支持"media queries"

    window.matchMedia();
  11. Android Android 的 webview 保存密码的问题

    可用 WebViewClient 的 onReceivedHttpAuthRequest 事件监听。详见这里。

  12. JS 添加 Do Not Track(DNT),保护访客隐私

    大多数的网络浏览器的设置中有一个“Do Not Track”(DNT 即“不追踪”)设定,让用户能够控制自己的隐私信息被追踪的情况。 但是网站到底是否真的不追踪,还要看网站本身是否响应它 那么,做一个善良的网站,如果用户设置了Do Not Track,那么就保护一下他的隐私吧!

    if(!navigator.doNotTrack){
      // 这里面写搜集信息的脚本,如果开启DNT则不执行
    }

    同理,nodejs的:

    var dnt=function(){
      return (headers['HTTP_DNT']==1)
    }

    ref:http://blog.regou.me/?p=721

  13. 解决网站内容存在多个版本时,指定规范链接,帮助解决内容重复收录问题

    <link rel="canonical" href="http://www.domain.com/index.html" /> 

    有利于 SEO,注意地址不能跨域。

  14. DNS Prefetch

    <link rel="dns-prefetch" href="http://hm.baidu.com/">
    

    DNS Prefetch也就是 DNS 预获取,也是前段优化的一部分。在前段优化中关于 DNS 的有两点:一是减少 DNS 的请求次数,第二个就是进行 DNS 预先获取。DNS Prefetch 应该尽量的放在网页的前面,推荐放在 <meta charset=”/> 后面。

  15. Link Prefetching

    <link rel="prefetch" href="http://daker.me/2013/05/hello-world.html" />
    <link rel="prefetch" href="http://daker.me/assets/images/avatar.png" />
    

    Link Prefetching 特性允许开发者在页面加载的时候预先加载他们希望指定的页面或元素。你也能够使用 prerendering 特性令你的网站速度更快,浏览器能够在后台获取并渲染整个页面,用户点击相应链接时再为用户展示该页面。

样式类

  1. 自适应布局模式

    在编写 CSS 时,不建议把容器的宽度定死。为达到适配各种手持设备,对 ipad、itouch、ipod、iphone、android、web safarik、chrome 都能够正常的显示,你无需再次考虑设备的分辨率。

  2. 禁止浏览器默认行为

    a, img{
      /* 禁止用户在新窗口打开页面、如何禁止用户保存图片\复制图片 for iOS */
      -webkit-touch-callout:none;
    }
    
    *{
      /* 禁止用户选中文字 for iOS */
      -webkit-user-select : none;
      /*很多Android 浏览器的 a 链接有边框,这里取消它*/
      -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
    }

    安卓手机取消长按出现“复制”按钮的话,要修改 Webview 默认行为:

    webView.setOnLongClickListener(new OnLongClickListener(){
    	public boolean onLongClick(View v) {
    		return true;
    	}
    });

  3. 如何解决盒子边框溢出

    当你指定了一个块级元素时,并且为其定义了边框,设置了其宽度为100%。在移动设备开发过程中我们通常会对文本框定义为宽度100%,将其定义为块级元素以实现全屏自适应的样式,但此时你会发现,该元素的边框(左右)各1个像素会溢了文档,导致出现横向滚动条,为解决这一问题,我们可以为其添加一个特殊的样式 -webkit-box-sizing:border-box; 用来指定该盒子的大小包括边框的宽度。

  4. 解决 CSS3 无法编写高光和内发光

    这个时候你不妨使用 -webkit-border-image 来定义这个按钮的样式。 见下面正确代码和效果图:

    <style type="text/css">
    .bbb{width:300px; height:40px; line-height:40px;border:1px solid #dcdcdc;box-shadow:0px 0px 10px rgba(0,0,0,0.2) inset;border-radius:10px;}
    </style>
    
    
    <div class="bbb">ttttttttttttttttttttt</div>

  5. iOS 4 没有 float:fixed

    苹果用户一般都会升级他们的操作系统,升级到 iOS 5 之后的版本就可以了。因此可以不考虑该问题的兼容性。

  6. 使用 LESS 样式框架 include 模板问题

    网页中只需 include xx.less 文件一次,其余的在那个 xx.less 中引入而不是与 xx.less 同级平衡,否则会出现重复加载的问题。

  7. Android 2.x 样式 active 失效

    其实点击那一下使用 cssSelecto:active 比 cssSelector:hover 更符合点击的效果,特别在列表滚动时尤其明显。但 Android 2.x 样式 active 失效,只好用 hover。如果用 js 实现,可参考如下:

    /**
     * 模拟 el:active
     * @param {Element} ul 参数为<ul></ul>元素
     */
    function onActive(ul){
    	// ONLY FOR Android 2.x? Yes!
    	// 检测是否 android 2.x 的属性,你可以依赖你自己的方案,我的就不贴了,比较简单的。
    	// if (!window.navigator.isAndroid_2) {
    		// return ul; //尽管该函数不工作,也要返回 this,以方便链式调用
    	// }
    	
    	// add Highlight
    	ul.addEventListener('touchstart', function (e){
    		var targetEl = e.target;
    		while(targetEl && targetEl.tagName != 'LI'){// 默认为 li 修改样式
    			targetEl = targetEl.parentNode; 		// 找到要操作的目标元素为止
    		}
    		// do sth……
    		console.log(targetEl.tagName);
    		targetEl.addCls('active');
    	});
    
    	// remove Highlight
    	ul.addEventListener('touchend',   function (e){
    		var targetEl = e.target;
    		while(targetEl && targetEl.tagName != "LI"){
    			targetEl = targetEl.parentNode; // 找到要操作的目标元素为止
    		}
    		// do sth……
    		console.log(targetEl.tagName);
    		targetEl.removeCls('active');
    	}); 
    	
    	return ul; // 方便链式调用
    }

    CSS 样式如下:

    /* 点击效果 */
    ul.x_list li:active, ul.x_list li.active {
        background-image: -webkit-gradient(linear, center top, center bottom, from(lightGrey), to(white));
    }

页面特效类

  1. 阻止页面整体滚动

    document.body.addEventListener('touchmove', function(event) {
      event.preventDefault();
    }, false); 
  2. 去掉浏览器地址栏

    window.setTimeout(scrollTo, 0, 0, 0);
    

    这句代码必须放在 window.onload 里才能够正常的工作,而且你的当前文档的内容高度必须是高于窗口的高度时,这句代码才能有效的执行。

  3. iOS 中如何获取滚动条的值

    桌面浏览器中想要获取滚动条的值是通过 document.scrollTop 和 document.scrollLeft 得到的,但在 iOS 中你会发现这两个属性是未定义的,为什么呢?因为在 iOS 中没有滚动条的概念,在 Android 中通过这两个属性可以正常获取到滚动条的值,那么在 iOS 中我们该如何获取滚动条的值呢?通过 window.scrollY 和 window.scrollX 我们可以得到当前窗口的 y 轴和 x 轴滚动条的值。

  4. 无法使用 Applicatipon Cache

    可以考虑使用 localStorage 代替。

  5. 复位 Applicatipon Cache 的一个办法

    在我们的3G版网站的项目中使用了html5 application cache,将大部分图片资源、js、css等静态资源放在manifest文件中。没想到上线第一天就遇到了严重问题:application cache会默认缓存当前页面!!!就算我们有如下设置:NETWORK:*也就是说,对于所有的动态页面,application cache会缓存起来,用户怎么刷新都是老的!而且手机浏览器还很难清除掉,也不支持js清除!花了一个上午,尝试了很多办法,查了很多资料,都没能清除掉客户端的缓存。一上午被用户投诉惨了。最后还是万能的stackoverflow救了我:
    Do not use appcache unless it is REALLY 100% EXACTLY WHAT YOU WANT TO DO Even if it IS 100% EXACTLY WHAT YOU WANT TO DO,
    *DO NOT* use appcache until you are 100% CERTAIN that you are not going to make a single change to that page (or any file that it links to) for a LONG time. Delete the manifest file from the server -- if the browser can't find the manifest file, then it will clear its cache... ...this will also turn caching off for everyone. Don't turn it on again until it's 100% CORRECT Dealing with appcache is miserable, often.
    解决办法很简单,在服务器端删除掉manifest文件,并且慎用application cache

  6. Safari 日期转换

    这是 Safari 浏览器的一个 bug,故桌面版和移动版都会有。不能用常规的 Date.format 方法解析日期类型。可尝试一下下面的补丁。

    var regexp = /[- :]/;
                            
    var _begin = (program.begin).split(regexp);
    var _end   = (program.end).split(regexp);
                            
    var begin  = new Date(_begin[0], _begin[1]-1, _begin[2], _begin[3], _begin[4], _begin[5]);
    var end    = new Date(_end[0], _end[1]-1, _end[2], _end[3], _end[4], _end[5]);
    var now    = new Date;
                            
    var arr = (program.begin).split(regexp);
    //var date = new Date(arr[0], arr[1]-1, arr[2], arr[3], arr[4], arr[5]);
    
  7. iOS 不能override UserAgent?

    如果是的话,那就缺乏轻松识别“基座模式”的途径。在 Android 上,重写 ua 却是一件轻易的事情。不过可以用以下方法代替:window.navigator.standalone 可用于判断当前web app是否从主屏启动。注意,这只在ios设备有效。

  8. 区域滚动

    要在一个 div 产生一个可滚动的区域,默认下是完全没有硬件加速的滚动效果的,效率很差,一顿一顿的滚动用户体验相当的不好。无论 iOS 和 android 都是,即使你使用 iframe 的也不行。不过苹果开发人员能意识到这个问题真的很“蛋疼”,从 iOS 5 开始于 overflow 项提供一个 scroll 的属性,使得苹果手机上可以有加速的区域滚动。但反观安卓方面,似乎很不负责任,到 4.1 都没有收到风声说优化此问题。解决方案有很多种,有人也曾经归纳过。比较主流的方法使用 iScroll 库。

  9. Android 4.0.下 touchend 滑动不能触发

    又是一个很蛋疼的问题。

  10. Android 4.0 transform 3D 极慢

    综上安卓 4.x WebView 所带来的问题,只能说,新的版本不一定好。android 2.x 都没有该问题。

  11. 制作跑马灯特效时的两个移动的不同

    尽管两者同时作用于一个控件(或 div )之上,但其性质是不一样的,一个是平移(move),相对于 D&D 的水平方向移动,是跟随手指移动着的;另外一个是滚动(scrollTo),跳到指定的哪一帧。

  12. 制作跑马灯使用 left/top 与使用 transformX/Y 的不同

    坐标系没有发生变化。不过 css3 的方式可以要求 mover 元素不为绝对定位。

  13. 检测是否已连网,以及网络速度

    最通用的:

    if (window.navigator.onLine) {
      alert('online')
    } else {
      alert('offline');
    }
    // in IE 8 "online" and "ofline" events are raised on the document.body, under IE 9 - on both document.body and window
    window.addEventListener("offline", function(e) {alert("offline");});
    window.addEventListener("online", function(e) {alert("online");});
    

    判断是否 wifi 网络

    if (navigator.connection.type==navigator.connection.WIFI) { 
       // code for WiFi connections (high-bandwidth)  
    }

    写成一个函数:

    /**
     * 检测是否已连网,以及网络速度。
     * @return {String} [description]
     */
    function netDetect(){
    	//alert(window.navigator.userAgent);
    	var connection, connectionSpeed;  
    	  
    	// create a custom object if navigator.connection isn't available  
    	connection = navigator.connection || {'type':'0'}; 
    
    	switch(connection.type){
    		case connection.ETHERNET:
    		case connection.WIFI:
    			connectionSpeed = 'highbandwidth'; 
    		break;
    		case connection.CELL_3G: 
    			connectionSpeed = 'mediumbandwidth'; 
    		break; 
    		case connection.CELL_2G: 
    			connectionSpeed = 'lowbandwidth'; 
    		break; 
    		case connection.UNKNOWN:
    		default: 
    			connectionSpeed = 'noConnect';
    	}
    	
    	return connectionSpeed;
    } 
    
    function is_Android_Wifi(){
        var connection = navigator.connection;
        if(window.navigator.isAndroid && (connection.type == connection.ETHERNET || connection.type == connection.WIFI))
            return true;
        else return false;
    }
  14. iOS 5 下通过 url 快速访问应用

    他们是直接将网页进行Base64编码,省的创建一堆页面,将该页面添加到主屏幕后 meta里的图标信息就生效了,伪装成一个系统应用,然后再点击开这个伪装的应用的时候 js判断 window.navigator.standalone==true 的时候 触发点击 href=“prefs:root=MESSAGES” 。最核心的是iOS5 可以href prefs:访问到应用,window.navigator.standalone的判断很巧妙,base64解码一下就清楚了。
    参考:
    http://www.zhihu.com/question/19916323/answer/13342363
    http://holgr.com/blog/2011/11/no-jailbreak-necessary-how-to-quickly-access-ios-settings-on-your-ipad-iphone-or-ipod/

  15. 事件委托 Event Delegation 之循环 vs 递归

    都是集中在如何获取父级元素(因为是“冒泡”所以是获取父元素,如果是“捕获”方式则是获取子元素)。初步看了, 循环好一点,起码不会死循环。

    // 递归方式
    /**
     * this 应为 CSS Selector
     * @param {Event} e
     */
    function removeHighlight(e){
    	var targetEl = e.target;
    	if(targetEl && targetEl.tagName == this.toUpperCase()){
    		targetEl.removeCls('active');
    	}else if(targetEl){
    		arguments.callee.call(this, {
    			target : targetEl.parentNode
    		});
    	}
    }
    
    ul.addEventListener(highEvent_out, removeHighlight.bind(el_cssSelector || 'LI'));
    
    // 循环方式
    function removeHighlight(e){
       var targetEl = e.target;
       while(targetEl && targetEl.tagName != 'LI'){// 默认为 li 修改样式
          targetEl = targetEl.parentNode;         // 找到要操作的目标元素为止
       }
       // do sth……
       console.log(targetEl.tagName);
       targetEl.removeCls('active');
    }
    

开发、调试技巧

  1. 手机上不容易复制、粘贴,有啥好办法?

    可以通过 QQ 发消息,但多个 QQ 同时登陆又有另外衍生的问题。如果是网址,推荐使用二维码的方式。给手机装个二维码扫描软件,然后把 url 放到在线的二维码生成,如http://www.liantu.com/,之后用扫一下就可以啦。

  2. 使用 SourceMap 时记得要把未压缩、未混淆的文件也放上去。


Bugs:

IOS4的日期类转换时有问题

http://stackoverflow.com/questions/5324178/javascript-date-parsing-on-iphone


Click事件tap事件傻傻分不清


AppCachemanifest)在phonegap模式下失效。

http://www.sencha.com/forum/showthread.php?175104-iOS-Fullscreen-webapp-manifest-file-gets-ignored


AppCache测试的地址:

回流 reflow重绘repaint问题

http://www.blogjava.net/BearRui/archive/2010/05/10/web_performance_repaint_relow.html

p.s Web页面性能测试工具,分别是:dynaTrace(测试ie),SpeedTracer(测试Chrome)


目录
相关文章
|
6天前
|
Web App开发 缓存 JavaScript
WKWebView相对UIWebView的优劣势
WKWebView相对UIWebView的优劣势
15 1
|
Android开发
看清安卓自定义view中触摸事件的“盲区”
今天的工作仍然在思考自定义view,因为需要调服务器接口,而这需要一些参数去其他地方拿,不在我调自定义view的页面,所以我希望能封装好这个自定义view,对外只要开放相应监听接口即可
|
存储 JSON 缓存
大麦 Android 选座场景性能优化全解析
大麦 Android 选座场景性能优化全解析
394 1
大麦 Android 选座场景性能优化全解析
|
前端开发 JavaScript Android开发
利用鸿蒙 JavaUI 框架的 WebView 加载本地冰墩墩网页
最近冰墩墩也太火了,各路大神纷纷表示用代码画冰墩墩,而我也刚好看到一个前端大神 Austin 用 JavaScript 前端写了一个冰墩墩,大家可以下载代码,本地打开就可以看到这个可爱的冰墩墩了。代码在后文参考资料中,大家可以自己下载。
利用鸿蒙 JavaUI 框架的 WebView 加载本地冰墩墩网页
|
存储 移动开发 缓存
Webview秒开探索:让你的H5“快人一步”
作为前端技术的重要衡量指标之一,首屏渲染效率无疑前端老生常谈的话题了。这篇文章就来聊下如何在常见的H5环境下,做到页面秒开。
Webview秒开探索:让你的H5“快人一步”
|
Android开发 容器
史上最好的Android事件分发文章
史上最好的Android事件分发文章
史上最好的Android事件分发文章
|
移动开发 前端开发 JavaScript
鸿蒙-webview的使用和JS交互(附源码)【鸿蒙开发04】
日常我们在开发项目时,为了项目快速的开发和迭代,难免会用到H5页面。使用鸿蒙进行项目开发时,也一样免不了要加载H5页面,在移动开发中打开H5页面需要使用WebView组件。同时,为了和H5页面进行数据交换,有时候还需要借助JSBridge来实现客户端与H5之间的通讯。 日常我们在开发项目时,为了项目快速的开发和迭代,难免会用到H5页面。使用鸿蒙进行项目开发时,也一样免不了要加载H5页面,在移动开发中打开H5页面需要使用WebView组件。同时,为了和H5页面进行数据交换,有时候还需要借助JSBridge来实现客户端与H5之间的通讯。 那么鸿蒙之中用到的技术是什么呢?WebView 在此之前,
808 0
|
Web App开发 移动开发 Dart
闲鱼正在悄悄放弃 Flutter 吗?
闲鱼在 2017 年引入 Flutter,当时的 Flutter 还远未成熟,行业内也没有把 Flutter 放入已有工程体系进行开发的先例。
316 0
闲鱼正在悄悄放弃 Flutter 吗?
|
Web App开发 移动开发 前端开发
行业资讯 | Android WebView 致安卓应用闪退,mPaaS 助你规避这波 Bug
近日,大量安卓用户因 WebView 发生故障而出现应用闪退,而通过使用 mPaaS 集成独立的 UC 浏览器内核以及容器与离线包技术,即可规避这类长期令众多安卓开发同学头疼不已兼容性问题
1110 0
行业资讯 | Android WebView 致安卓应用闪退,mPaaS 助你规避这波 Bug
|
缓存 移动开发 前端开发
为什么那么多公司都钟爱Flutter?
1. 中小公司维护一个App的成本好高呀,有没有办法可以降低成本的可能性,但是又不想让代码缺少维护? 2. 有没有方案可以实现一份代码可以运行在多个平台,减少沟通成本呢?