這2年來,移動h5開發逐漸成為一種主流,也不斷趨向於成熟。硬件和瀏覽器的不斷更新,曾經的瀏覽器兼容也不再是開發者的噩夢。
接觸h5開發一年多,從最初的新手到現在,陸陸續續遇到過很多坑。這里把想到的一些經驗與資源羅列出來,給剛入h5的同學帶來一些幫助。該文章會持續更新。
內容比較多,可以點擊下方『懸浮菜單按鈕』進行選擇需要閱讀的章節。
基礎知識
新手建議看看下面的在線教程。
html,css,JavaScript,jQuery在線教程:
w3school在線教程:http://www.w3school.com.cn/
菜鳥教程:http://www.runoob.com/
參考手冊:
jQuery:http://hemin.cn/jq/
css:http://css.doyoe.com/
h5頁面基本組成
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<title>title</title>
</head>
<body>
</body>
meta viewport模板
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
<meta content="yes" name="apple-mobile-web-app-capable">
<meta content="black" name="apple-mobile-web-app-status-bar-style">
<meta content="telephone=no" name="format-detection">
<meta content="email=no" name="format-detection">
<title>標題</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
這里開始內容
</body>
</html>
以上支持響應式布局設計。
有用的js類庫
jQuery
這個必須學會的。
在線教程:http://www.w3school.com.cn/jquery/index.asp
在線手冊:http://hemin.cn/jq/
Zepto
Zepto和jQuery基本是一樣的,只是由於其體積更小,適合移動端使用。 如果你會用jquery,那么你也會用zepto。注意,zepto並沒有實現jQuery的所有功能,這也就意味着jQuery的插件Zepto不能直接拿來用。
最新版是1.1.6。
API參考:http://www.css88.com/doc/zeptojs_api/
github: https://github.com/madrobby/zepto
注意:
Zepto默認構建包含以下模塊:
Core, Ajax, Event, Form, IE.
也就是意味着下列模塊可能需要自己加入或重新編譯進去:
detect
、fx、fx_methods、assets、data、deferred、callbacks、selector
、touch
、gesture、stack、ios3。
underscore
為JavaScript提供了很多好用的方法,可以當工具函數庫使用。
Underscore提供了100多個函數,包括常用的: map, filter, invoke — 當然還有更多專業的輔助函數,如:函數綁定, JavaScript模板功能,創建快速索引, 強類型相等測試, 等等.
API參考:http://www.css88.com/doc/underscore/
backbone
前端的MVC框架。Backbone.js為復雜WEB應用程序提供模型(models)、集合(collections)、視圖(views)的結構。
初學者了解即可。
API參考:http://www.css88.com/doc/backbone/
KISSY
官網說是一款強大的JavaScript框架。實質就是類jQuery+UI組件
,淘寶網自己用的。感興趣的可以了解了解。
http://docs.kissyui.com/
前端UI框架
想要快速構建一個網站或應用,尤其在初入移動端開發,對移動端布局、響應式不熟悉的時候,使用已有的UI框架可以節省很多時間。網上有很多開源的UI框架。
如何選擇呢?
1、組件小(CSS+JS 總大小最好200KB以內)
2、提供常用組件:如表單、按鈕、對話框、toast等。最好還有日歷、時間選擇、TAB標簽、Popup、操作表、路由可供使用。
3、支持響應式。必須的。
下面推薦幾款供使用。曾經都使用過。
移動端:
FrozenUI:http://frozenui.github.io/
SUI Mobile:http://m.sui.taobao.org/
weui:https://github.com/weui/weui
缺陷與優點:FrozenUI缺少日歷、時間選擇、操作表、路由等組件,但體積很小,使用簡單。SUI路由不好用,體積偏大。這兩款均依賴Zepto。weui目前僅提供CSS組件,沒有集成JS。
Web端:
Bootstrap:http://www.bootcss.com/
ZUI:http://zui.sexy/#/
缺陷與優點:Bootstrap算是很有名的了。WEB建站必備,是很多人接觸的第一個UI框架,建議學會。直接使用Bootstrap3版本即可。后台管理可以使用ZUI。
js插件
彈出層
artDialog 4.1.7
http://lab.seaning.com/
layer(jQuery彈出層插件)
http://layer.layui.com/
layer.mobile
http://layer.layui.com/mobile/
SweetAlert:漂亮的alert美化插件
http://www.wufangbo.com/sweet-alert/
表單驗證
jquery.validate:http://www.cnblogs.com/52fhy/p/4953556.html
幻燈片
jquery.SuperSlide
http://www.superslide2.com/demo.html
Swiper2
http://2.swiper.com.cn/
編輯器
kindeditor
http://kindeditor.net/demo.php
UEditor
http://ueditor.baidu.com/website/index.html
聯想輸入(自動補全)
autocomplete:http://www.cnblogs.com/52fhy/p/4456092.html
bigautocomplete:http://www.cnblogs.com/52fhy/p/4455988.html
日期選擇
jquery-datepicker
http://www.helloweba.com/view-blog-168.html
My97DatePicker
http://www.my97.net/
pickadate.js響應式時間選擇器(依賴jQuery)
https://github.com/amsul/pickadate.js
layDate - js日期控件與時間插件官方講解
http://laydate.layui.com/
圖片畫廊&放大
baguetteBox.js響應式畫廊插件(純JS)
http://www.cnblogs.com/52fhy/p/4836463.html
圖片懶加載
lazyload.js: http://www.cnblogs.com/52fhy/p/5344182.html
jquery.lazyload.js: http://www.appelsiini.net/projects/lazyload
圖標字體(iconfont)
在做移動端項目中,經常會用到很多小圖標,如首頁、分享、回復、贊、返回等,這些Icon(圖標)一般都是純色的。
我們一般有三種方式來展示這些圖標:
1、每個圖標對應一張圖片,通過設置圖片的大小完成;
2、將所有圖標放在一張圖片上,通過background-position
屬性進行偏移;
3、圖標字體解決方案:將圖標做成字體。
優缺點非分析:
1、方案1每個圖標都會被加載一次,增大服務器壓力;圖片放大會模糊;
2、方案2圖片僅會加載一次,但難點是設置好位移;不方便新增圖標;圖片放大會模糊;
3、方案3是這兩年新起的方案,不考慮舊瀏覽器的情況下,可以解決上述所有缺點:圖標矢量化,不會模糊;在一個字體文件內,不會多次請求;可以方便的添加新的圖標。
想深入了解的同學可以看下面資源:
圖標字體化淺談
http://www.cnblogs.com/52fhy/p/5296545.html
圖標字體資源匯總
iconfont可在線編輯,可導入導出
https://icomoon.io/app/#/select
阿里icon font字庫:圖標很多
http://www.iconfont.cn/
阿里媽媽M2UX的一個icon font字體圖標字庫
http://fontello.com/
Font Awesome, 為 Bootstrap 而創造的圖標字體
http://www.bootcss.com/p/font-awesome/
自動化集成
grunt
使用grunt合並壓縮js、css文件 :
http://www.cnblogs.com/52fhy/p/4954107.html
gulp
gulp.js - 基於流的自動化構建工具
http://www.gulpjs.com.cn/
一點 | gulp詳細入門教程
http://www.ydcss.com/archives/18
其它
手機拍照和上傳圖片
<input type="file">
的accept 屬性
<!-- 選擇照片 -->
<input type="file" capture="camera" accept="image/*" name="image" id="file">
<!-- 選擇視頻 -->
<input type="file" accept="video/*">
使用總結:
加了capture
屬性后h5有拍照功能
ios 有拍照、錄像、選取本地圖片功能
部分android只有選取本地圖片功能
winphone不支持
input控件默認外觀丑陋
去除瀏覽器按鈕默認樣式
發現在安卓和電腦上正常的按鈕到蘋果手機上不正常了,后來發現是瀏覽器有默認樣式。禁止就行了。
input {
-webkit-appearance: none;
}
隱藏滾動條
可以不顯示滾動條但頁面依舊可以滾動。僅webkit內核瀏覽器中有效(Chrome,Safari)。嫌滾動條不好看的同學可以試試。
::-webkit-scrollbar{
width: 0px
}
字體單位font-size選擇px還是rem
px
: 這個是絕對大小,我們一般使用px來設置我們的文本,因為他比較穩定和精確。
em
: 相對大小,相對於父元素的值,計算公式: 需要轉換的像素值 / 父元素的font-size = em值
rem
: 相對大小,W3C官網描述是font size of the root element
,即rem是相對於根元素。
對於只需要適配少部分手機設備,且分辨率對頁面影響不大的,使用px即可。
對於需要適配各種移動設備,使用rem,例如只需要適配iPhone和iPad等分辨率差別比較挺大的設備。
詳細請閱讀:
CSS3中REM使用詳解
http://www.w3cways.com/1713.html
jQuery on()方法代替live()方法動態綁定事件
從 jQuery 1.7 開始,不再建議使用
.live()
方法。請使用.on()
代替 來添加事件處理。使用舊版本的用戶,應該優先使用.delegate()
來替代.live()
。
手冊里說建議使用 .on()
代替.live()
方法,但是沒有給出例子。
之前項目中用.on()
來測試結果發現,居然動態生成的標簽點擊了沒反應,而.live()
方法卻能夠支持。后來才發現,jQuery 使用.on()
綁定動態生成的元素時,不能直接用該對象操作,而是選擇其非動態生成的父節點然后再找到本身才能達到效果。例如:
$("p").live("click", function(){
$(this).after("<p>Another paragraph!</p>");
});
這里的p
標簽是動態生成的,直接使用.on()
是沒辦法觸發.click
事件的。但這樣是可以的:
$(document).on("click",'p', function(){
$(this).after("<p>Another paragraph!</p>");
});
選擇父節點document
再找到動態生成的p
標簽。
動態引入js文件
var oHead = document.getElementsByTagName('head')[0];
var oScript= document.createElement("script");
oScript.type = "text/javascript";
oScript.src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js";
oHead.appendChild(oScript);
動態創建meta屬性
var meta = document.createElement('meta');
meta.setAttribute('name', 'viewport');
meta.setAttribute('content', 'initialwidth=device-width,initial-scale=1');
document.getElementsByTagName('head')[0].appendChild(meta);
垂直居中 - 使用 position 和 transform
除了使用 padding 和 line-height 屬性外,我們還可以使用 transform 屬性來設置垂直居中:
.center {
height: 200px;
position: relative;
border: 3px solid green;
}
.center p {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
}
參考:CSS 布局 – 水平 & 垂直對齊 | 菜鳥教程
http://www.runoob.com/css/css-align.html
CSS設置文字省略隱藏
.ellipsis_txt {
display: -webkit-box;
-webkit-line-clamp: 2;
overflow: hidden;
word-break: break-all;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
}
-webkit-line-clamp: 2;
表示最多顯示2行文字。
另外一種,默認顯示一行:
.ellipsis{
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
width: 95%;
}
必須是塊級元素,必須指定寬度。
元素float后,父元素沒有高度問題
在CSS里定義了如CLASS類這樣的浮動后,你會發現父div名box沒有高度,所以又時候你可能感覺到父div的margin沒有效果,這種情況下,你只需要給父div加個overflow:hidden
就可以了,譬如
.box{overflow:hidden}
更多閱讀:[譯] 關於CSS中的float和position (父容器div內的子元素div為float時,父元素無法撐開(或高度自適應)的解決方式)
fixed定位與虛擬鍵盤沖突問題
移動端里 輸入框input獲取焦點得時,虛擬鍵盤會把fixed元素頂上去。
使用媒體查詢解決:
@media (max-height: 400px) {
.footer {
display: none;
}
}
div之間的空隙?
當兩個div緊挨着的時候沒有空隙,中間有空格或換行就有了空隙,這是為什么?
使用 display: inline-block 會導致元素之間有空隙
解決方法: 父元素設置 font-size: 0;
微信不支持支付寶方法
使用iframe。在alipay_submit.class.php
文件中增加一個方法:
/**
* 使用iframe嵌入支付寶支付
* @date: 2016年2月17日 下午12:50:05
* @author: YJC
*/
function buildRequestUrl($para_temp, $method, $button_name) {
//待請求參數數組
$para = $this->buildRequestParaToString($para_temp);
$url = $this->alipay_gateway_new. $para;
$sHtml = '<head><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0"/>
</head>';
$sHtml .= '<iframe src="'.$url.'" width="100%" height="100%" frameborder="0"></iframe>';
return $sHtml;
}
注意這里的$this->alipay_gateway_new
是http://wappaygw.alipay.com/service/rest.htm
。
然后調用時將默認的buildRequestForm
改為buildRequestUrl
方法即可。
但是有個問題,我們設置的callback頁面(一般是訂單詳情,顯示支付成功與否的頁面),這時候也在iframe里面,我們需要跳出。方法是:
在callback頁面增加一段js代碼;
if(top.location!=self.location)top.location=self.location;
就可以了。
基於jQuery/zepto實現選項自動選中
首先js里加上:
$(function () {
$('.js-select').each(function (i,v) {
var idx = $(this).data('val');
$(this).find("option[value='" + idx + "']").attr("selected",true);//選中已勾選的
});
$('.js-radio').each(function (i,v) {
var idx = $(this).data('val');
$(this).find("input[value='" + idx + "']").attr("checked",true);//選中已勾選的
});
});
然后在html里加上相應的.js-select
、.js-radio
類,並給出值data-val:
<select class="js-select" data-val="1">
<option value="">模式</option>
<option value="1">公開</option>
<option value="2">私有</option>
</select>
就能根據data-val自動選中選項。
網頁重載方法
/**
* 刷新當前頁面
*/
function reloadCurrent(timeout){
setTimeout(function(){
window.location.reload();//刷新當前頁面
}, timeout || 0);
}
ajax刪除
/**
* 發送request
* @param params
* @param uri
* @param callback
* @param type
*/
function send_request(params, url, callback, type) {
$.ajax({
type: type || "POST",
data: params,
dataType: "json",
timeout: 200000,
url: url,
success: function(data) {
callback && callback(data);
},
error:function(){
layer.alert('請稍后再試');
}
});
}
$(function () {
//ajax刪除
$(document).on('click','.js_del_ajax', function () {
var title = $(this).data('title') || '確定要刪除嗎?';
var href = $(this).data('href');
var uri = $(this).data('uri');
var id = $(this).data('id');
var params = $(this).data();
var url = href ? href : site_url + uri;
layer.confirm(title, {
btn: ['確定','取消'] //按鈕
}, function(){
send_request(params, url, function (response) {
if(response.code == 1){
layer.msg('成功');
setTimeout(function(){
window.location.reload();
}, 200);
}else{
layer.msg(response.info);
}
});
}, function(){
});
});
});
基於layer+laytpl實現管理后台彈窗編輯
需要下載layer和laytpl:
http://res.layui.com/download/layer/layer-v3.1.0.zip
http://www.jb51.net/codes/207072.html
現在laytpl已經被包含在layui里了。http://www.layui.com/
直接上代碼:
<script type="text/template" id="js-set-tpl">
<style>
.dialog_wrap{width: 90%;margin: 10px;}
.dialog_wrap .column{margin: 10px 5px;}
.dialog_btn_ok{text-align: right;}
.clearfix:after,.form-group:after {
clear: both;
display: table;
content: " ";
}
</style>
<form name="js-set-form" action="">
<div style="margin: 15px;">
<div class="row">
<div class="col-xs-12">
說明:<textarea style="width: 100%" rows="3" name="desc" placeholder="請輸入說明"></textarea>
</div>
</div>
<div style="margin: 5px;text-align: right;"><input type="button" class="am-btn am-btn-primary am-btn-xs js-laytpl-save" value="保存"></div>
</div>
</form>
</script>
<script type="text/javascript">
$(function () {
var dialog_set;
$('#js-set').on('click', function () {
var tpl = $('#js-set-tpl').html();
dialog_set = layer.open({
type: 1,
skin: 'layui-layer-rim', //加上邊框
area: ['620px', 'auto'], //寬高
closeBtn: 1, //不顯示關閉按鈕
shadeClose: true, //開啟遮罩關閉
title:'設置',
content: tpl,
success: function () {},
cancel: function(index, layero){}
});
});
$(document).on('click','.js-laytpl-save', function () {
var data = $($('form[name=js-set-form]').get(0)).serializeArray();
// console.log(data);return false;
var index = layer.load(0, {shade: false});
$.ajax({
type: "POST",
data: data,
dataType: "json",
url: '/Admin/save',
success: function(data) {
layer.close(index);
// console.log(data);
if(data.code == 1){
layer.msg('成功');
layer.close(dialog_set);
setTimeout(function(){
window.location.reload();
}, 200);
}else{
layer.alert(data.msg);
return false;
}
},
error:function(){
layer.alert('請稍后再試');
}
});
});
});
</script>
基於layer當前頁面打開窗口
$(function () {
//當前頁面打開窗口
$(document).on('click', '.js_iframe_dialog', function () {
var href = $(this).data('href');
var title = $(this).data('title') || '查看詳情';
layer.open({
type: 2,
title: title,
shadeClose: true,
shade: 0.8,
area: ['90%', '90%'],
maxmin: true, //開啟最大化最小化按鈕
content: href //iframe的url
});
});
});
持續更新中。。。