如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
html與css:
<!DOCTYPE html>
</html>
JS:
var waterfall = function(wrap, boxes) {
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
/* 標簽重定義 */
* {
margin: 0;
padding: 0;
border: none;
}
body {
background: #ddd;
}
img {
border: none;
}
a {
text-decoration: none;
color: #444;
}
a:hover {
color: #999;
}
/* wrap */
#wrap {
position: relative;
width: auto;
height: auto;
margin: 0 auto;
}
#wrap>div {
float: left;
box-sizing: border-box;
width: 280px;
height: auto;
margin: 10px;
padding: 10px;
border-radius: 5px;
background: #fff;
}
#wrap>div>img {
width: 260px;
margin: 0 auto;
}
#wrap>div>a {
display: block;
font-size: 18px;
font-weight: bold;
line-height: 40px;
text-align: center;
}
</style>
</head>
<body>
<div id="wrap">
<div>
<img src="img/1.jpg">
<a target="_blank">第一張 路飛與艾斯</a>
</div>
<div>
<img src="img/2.jpg">
<a target="_blank">第二張 艾博</a>
</div>
<div>
<img src="img/3.jpg">
<a target="_blank">第三張 路飛</a>
</div>
<div>
<img src="img/4.jpg">
<a target="_blank">第四張 艾斯</a>
</div>
<div>
<img src="img/5.jpg">
<a target="_blank">第五張 女王</a>
</div>
<div>
<img src="img/6.jpg">
<a target="_blank">第六張 香吉士</a>
</div>
<div>
<img src="img/7.jpg">
<a target="_blank">第七張 艾斯</a>
</div>
<div>
<img src="img/8.jpg">
<a target="_blank">第八張 霸氣</a>
</div>
</div>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/script.js"></script>
</body>
// 獲取屏幕可以顯示的列數
var boxWidth = boxes.eq(0).width() + 40;
var windowWidth = $(window).width();
var colsNumber = Math.floor(windowWidth / boxWidth);
// 設置容器的寬度
wrap.width(boxWidth * colsNumber);
// 定義一個數組并存儲每一列的高度
var everyHeight = new Array();
for (var i = 0; i < boxes.length; i++) {
if (i < colsNumber) {
everyHeight[i] = boxes.eq(i).height() + 40;
} else {
var minHeight = Math.min.apply(null, everyHeight);
var minIndex = getIndex(minHeight, everyHeight);
boxes.eq(i).css({
'position': 'absolute',
'top': minHeight,
'left': boxes.eq(minIndex).position().left,
'opacity': '0'
}).stop().animate({
'opacity': '1'
}, 1000);
everyHeight[minIndex] += boxes.eq(i).height() + 40;
};
}
};
// 獲取最小列的索引
function getIndex(minHeight, everyHeight) {
for (index in everyHeight) {
if (everyHeight[index] == minHeight) {
return index;
};
};
};
$(document).ready(function(event) {
var wrap = $('#wrap');
var boxes = $('#wrap').children('div');
waterfall(wrap, boxes);
});
1.Json的格式
其實json就是對象。源生的js代碼并沒有類的概念。對象救就是object。對象有自己的屬性,也可以有自己的方法。json是一種輕量級的存儲和交換信息的語言。他有自己的格式。
較為簡單的json。里面只有簡單的對象,key+value的形式:
每個元素之間用逗號隔開。調用每個key的值可用語句。例如:CellInfo.UEAmunt,就可取出其中的值。
較為復雜的json。里面包含了對象。
例如這個UEGroup1,里面的元素不僅有簡單的key+value,還包含了三個對象。對象里的元素用{}括起來,彼此之間用逗號隔開。想具體訪問某個元素的值也是通過逐層key,例如:UEGrooup1.DBR1.DLPackageSize
動態的往json只增加元素,增加對象。
前面說的幾個都是靜態的,提前寫好的。那如果臨時想加一個元素,例如在Cellinfo這個json中相加一個number的元素:
CellInfo.number=10;
對于往json中添加對象。例如我們想把Cellinfo和UEGroup1這兩個object作為兩個元素加入到另外一個大的json中:
2.json的發送
json寫好后,發送給后臺。至于后臺怎么處理數據我們不關心。發送json的函數如下:
}
參數分別是后臺的地址,變量,方法。變量就是我們自己寫好的json,方法默認為post。例如我們想發剛剛的PETInfo
$.post('http://10.140.160.64:3012/users/ueinfo', PETInfo);
數據的發送、并獲取結果的實例:
需求描述:用戶填寫一系列的輸入框,前端獲取數據,封裝成json并發送給服務器,服務器會返回一個返回值,表示狀態。前端需要展示這個內容提示客戶。
3.json在本地的存儲
存儲數據有很多方法。這里我用的是localStorage。localStorage與cookie的區別如下:
① cookie在瀏覽器與服務器之間來回傳遞。
sessionStorage和localStorage不會把數據發給服務器,僅在本地保存
②數據有效期不同:
cookie只在設置的cookie過期時間之前一直有效,即使窗口或瀏覽器關閉。
sessionStorage:僅在當前瀏覽器窗口關閉前有效。
localStorage 始終有效,長期保存。
③cookie數據還有路徑的概念,可以限制cookie只屬于某個路徑下。
存儲大小也不同,cookie數據不能超過4k,sessionStorage和localStorage 雖然也有存儲大小的限制,但比cookie大得多,可以達到5M或更大。
④ 作用域不用
sessionStorage不在不同的瀏覽器窗口中共享;
localStorage在所有同源窗口中都是共享的;
cookie也是在所有同源窗口中都是共享的;
WebStorage 支持事件通知機制,可以將數據更新的通知發送給監聽者。Web Storage 的 api 接口使用更方便。
用localstage存儲json的實例:
將json取出來:
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
控制表格的多選和反選,直接上代碼,順便安利一個小知識點:tr的底邊框不顯示的問題,解決辦法是:table{border-collapse:collapse;}
-
<!DOCTYPE html>
-
<html>
-
<head>
-
<title></title>
-
<style>
-
*{margin:0;padding:0;}
-
table{border-collapse:collapse}
-
.detail_tb {width: 100%;border: 1px solid #ccc;}
-
.detail_tb .fied_header {height: 38px;line-height: 38px;border-left: none;border-bottom: 1px solid #ccc;background-color: #ececec;}
-
.detail_tb .fied_header th {text-align: center;border-right: 1px solid #ccc;color: #333;font-size: 14px;}
-
.detail_tb .fied_header th input {vertical-align: middle;}
-
.detail_tb tr {height: 38px;line-height: 38px;border-left: none;border-bottom: 1px solid #ccc;background-color: #fff;}
-
.detail_tb tr td {text-align: center;border-right: 1px solid #ccc;color: #666;font-size: 14px;}
-
.detail_tb tr td input {float: left;margin: 12px 5px 0 10px;}
-
.detail_tb tr td span {float: left;}
-
.detail_tb tr td select {display: inline-block;width: 90px;height: 24px;}
-
</style>
-
-
</head>
-
<body>
-
-
<table class="detail_tb" >
-
<thead>
-
<tr class="fied_header">
-
<th width="65"><input type="checkbox" value="number" id="number"> 序號</th>
-
<th width="110">孩子姓名</th>
-
<th width="130">家長電話</th>
-
<th width="110">介紹人孩子姓名</th>
-
<th width="130">介紹人電話</th>
-
<th width="150">報名時間</th>
-
<th width="100">分組情況</th>
-
<th width="100">拉新數量</th>
-
<th width="100">是否簽到</th>
-
<th width="100">是否發獎</th>
-
</tr>
-
</thead>
-
<tbody id="tbody">
-
<tr>
-
<td width="65"><input type="checkbox" value="" id="" ><span>1</span></td>
-
<td width="110">張三</td>
-
<td width="130">13888888888</td>
-
<td width="110">李四</td>
-
<td width="130">13888888888</td>
-
<td width="150">2016/08/6 21:00</td>
-
<td width="100">
-
<select name="" id="">
-
<option value="">未分組</option>
-
<option value="">1</option>
-
<option value="">2</option>
-
</select>
-
</td>
-
<td width="100">33</td>
-
<td width="100">是</td>
-
<td width="100">
-
<select name="" id="">
-
<option value="">否</option>
-
<option value="">獎品1</option>
-
<option value="">獎品2</option>
-
</select>
-
</td>
-
</tr>
-
<tr>
-
<td width="65"><input type="checkbox" value="" id=""><span>2</span></td>
-
<td width="110">張四</td>
-
<td width="130">13888888888</td>
-
<td width="110">李四</td>
-
<td width="130">13888888888</td>
-
<td width="150">2016/08/6 21:00</td>
-
<td width="100">
-
<select name="" id="">
-
<option value="">未分組</option>
-
<option value="">1</option>
-
<option value="">2</option>
-
</select>
-
</td>
-
<td width="100">33</td>
-
<td width="100">是</td>
-
<td width="100">
-
<select name="" id="">
-
<option value="">否</option>
-
<option value="">獎品1</option>
-
<option value="">獎品2</option>
-
</select>
-
</td>
-
</tr>
-
<tbody>
-
</table>
-
-
-
<script src="https://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
-
<script type="text/javascript">
-
// 全選和反選
-
$("#number").click(function () {
-
var isChecked = $("#number").prop("checked");
-
$("#tbody input").prop("checked", isChecked);
-
})
-
-
// 單獨選項控制全選
-
$("#tbody input").click(function () {
-
var allLength = $("#tbody input").length;
-
var checkedLength = $("#tbody input:checked").length;
-
if(allLength == checkedLength){
-
$("#number").prop("checked",true);
-
}else {
-
$("#number").prop("checked",false);
-
}
-
});
-
</script>
-
-
</body>
-
</html>
-
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
1.解決頁面使用overflow: scroll在iOS上滑動卡頓的問題?
首先你可能會給頁面的html和body增加了height: 100%, 然后就可能造成IOS上頁面滑動的卡頓問題。解決方案是:
(1) 看是否能把body和html的height: 100%去除掉。
(2) 在滾動的容器中增加:-webkit-overflow-scrolling: touch或者給body增加:body {overflow-x: hidden}。
2.ios頁面橡皮彈回效果遮擋頁面選項卡?
(1) 有時body和html的height: 100%去除掉問題可能就沒有了。
(2) 到達臨界值的時候在阻止事件默認行為
var startY,endY; //記錄手指觸摸的起點坐標 $('body').on('touchstart',function (e) { startY = e.touches[0].pageY; }); $('body').on('touchmove',function (e) { endY = e.touches[0].pageY; //記錄手指觸摸的移動中的坐標 //手指下滑,頁面到達頂端不能繼續下滑 if(endY>startY&& $(window).scrollTop()<=0){ e.preventDefault(); } //手指上滑,頁面到達底部能繼續上滑 if(endY<startY&& $(window).scrollTop()+ $(window).height()>=$('body')[0].scrollHeight){ e.preventDefault(); } })
有時也會碰見彈窗出來后兩個層的橡皮筋效果出現問題,我們可以在彈出彈出時給底層頁面加上一個類名,類名禁止頁面滑動這樣下層的橡皮筋效果就會被禁止,就不會影響彈窗層。 3.IOS機型margin屬性無效問題? (1) 設置html body的高度為百分比時,margin-bottom在safari里失效 (2) 直接padding代替margin 4.Ios綁定點擊事件不執行? (1)添加樣式cursor :pointer。點擊后消除背景閃一下的css:-webkit-tap-highlight-color:transparent; 5.Ios鍵盤換行變為搜索? 首先,input 要放在 form里面。 這時 "換行" 已經變成 “前往”。 如果想變成 “搜索”,input 設置 type="search"。 6.Jq對a標簽點擊事件不生效? 出現這種情況的原因不明,有的朋友解釋:我們平時都是點擊的A標簽中的文字了。 所以要想用JS模擬點擊A標簽事件,就得先往A標簽中的文字添加能被JS捕獲的元素,然后再用JS模擬點擊該元素即可。但是我覺得不合理,雖然找不到原因但是解決辦法還是有的。 (1)document.getElementById("abc ").click(); (2)$("#abc ")[0].click(); 7.有時因為服務器或者別的原因導致頁面上的圖片沒有找到? 這是我們想需要用一個本地的圖片代替沒有找的的圖片
<script type="text/javascript"> function nofind(){ var img=event.srcElement; img.src="images/logoError.png"; img.onerror=null; 控制不要一直跳動 } </script> <img src="images/logo.png" />8.transform屬性影響position:fixed?
(1)規范中有規定:如果元素的transform值不為none,則該元素會生成包含塊和層疊上下文。CSS Transforms Module Level 1不只在手機上,電腦上也一樣。除了fixed元素會受影響之外,z-index(層疊上下文)值也會受影響。絕對定位元素等和包含塊有關的屬性都會受到影響。當然如果transform元素的display值為inline時又會有所不同。最簡單的解決方法就是transform元素內部不能有absolute、fixed元素.
9.ios對position: fixed不太友好,有時我們需要加點處理?
在安卓上面,點擊頁面底部的輸入框,軟鍵盤彈出,頁面移動上移。
而ios上面,點擊頁面底部輸入框,軟鍵盤彈出,輸入框看不到了。。。查資料說什么的都有,iscroll,jquery-moblie,absolute,fixe,static都非常復雜,要改很多。。。
讓他彈出時讓滾動條在部
var u = navigator.userAgent, app = navigator.appVersion; var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios終端 if (isiOS) { $('textarea').focus(function () { window.setTimeout('scrollBottom()', 500); }); } function scrollBottom() { window.scrollTo(0, $('body').height()); }10.jq validate插件驗證問題?
(1)所以的input必須有name不然會出錯
11.有時手機會出現斷網的情況,我沒可能會對斷網的情況做一些處理?
(1)navigator.onLine可判斷是否是脫機狀態.
12.判斷對象的長度?
(1)用Object.keys,Object.keys方法返回的是一個數組,數組里面裝的是對象的屬性
var person = { "name" : "zhangshan", "sex" : "man", "age" : "50", "height" : "180", "phone" : "1xxxxxxxxxx", "email" : "xxxxxxxxx@xxx.com" }; var arr = Object.keys(person); console.log(arr.length);(2)Object.getOwnPropertyNames(obj).length
13.上一題我們用到了Object.keys與Object.getOwnPropertyNames他們的區別?
Object.keys定義:返回一個對象可枚舉屬性的字符串數組;
Object.getOwnPropertyNames定義:返回一個對象可枚舉、不可枚舉屬性的名稱;
屬性的可枚舉性、不可枚舉性:定義:可枚舉屬性是指那些內部 “可枚舉” 標志設置為 true 的屬性,對于通過直接的賦值和屬性初始化的屬性,該標識值默認為即為 true,對于通過 Object.defineProperty 等定義的屬性,該標識值默認為 false。
var obj = { "prop1": "v1" };
Object.defineProperty(obj, "prop2", { value: "v2", enumerable: false });
console.log(Object.keys(obj).length); //output:1 console.log(Object.getOwnPropertyNames(obj).length); //output:2 console.log(Object.keys(obj)); //output:Array[1] => [0: "prop1"] console.log(Object.getOwnPropertyNames(obj)); //output:Array[2] => [0: "prop1", 1: "prop2"]
綜合實例
var obj = { "prop1": "v1" }; Object.defineProperty(obj, "prop2", { value: "v2", enumerable: false}); console.log(obj.hasOwnProperty("prop1")); //output: true console.log(obj.hasOwnProperty("prop2")); //output: true console.log(obj.propertyIsEnumerable("prop1")); //output: true console.log(obj.propertyIsEnumerable("prop2")); //output: false console.log('prop1' in obj); //output: true console.log('prop2' in obj); //output: true for (var item in obj) { console.log(item); } //output:prop1 for (var item in Object.getOwnPropertyNames(obj)) { console.log(Object.getOwnPropertyNames(obj)[item]); } //ouput:[prop1,prop2]
14.移動開發不同手機彈出數字鍵盤問題?
(1)type="tel"
iOS和Android的鍵盤表現都差不多
(2)type="number"
優點是Android下實現的一個真正的數字鍵盤
缺點一:iOS下不是九宮格鍵盤,輸入不方便
缺點二:舊版Android(包括微信所用的X5內核)在輸入框后面會有超級雞肋的小尾巴,好在Android 4.4.4以后給去掉了。
不過對于缺點二,我們可以用webkit私有的偽元素給fix掉:
input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; appearance: none; margin: 0; }
(3)pattern屬性
pattern用于驗證表單輸入的內容,通常HTML5的type屬性,比如email、tel、number、data類、url等,已經自帶了簡單的數據格式驗證功能了,加上pattern后,前端部分的驗證更加簡單了。
顯而易見,pattern的屬性值要用正則表達式。
實例 簡單的數字驗證
數字的驗證有兩個:
<input type="number" pattern="d">
<input type="number" pattern="[0-9]*">
15.input[number]類型輸入非數字字符
js獲取的值是空;比如-12,+123等
16.Javascript:history.go()和history.back()的用法與區別?
簡單的說就是:go(-1):返回上一頁,原頁面表單中的內容會丟失;back():返回上一頁,原頁表表單中的內容會保留。history.go(-1):后退+刷新history.back():后退
之所以注意到這個區別,是因為不同的瀏覽器后退行為也是有區別的,而區別就跟javascript:history.go()和history.back()的區別類似。
Chrome和ff瀏覽器后退頁面,會刷新后退的頁面,若有數據請求也會提交數據申請。類似于history.go(-1);
而safari(包括桌面版和ipad版)的后退按鈕則不會刷新頁面,也不會提交數據申請。類似于javascript:history.back();
17.Meta基礎知識:
<meta name="viewport"content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
// width 設置viewport寬度,為一個正整數,或字符串‘device-width’
// height 設置viewport高度,一般設置了寬度,會自動解析出高度,可以不用設置
// initial-scale 默認縮放比例,為一個數字,可以帶小數
// minimum-scale 允許用戶最小縮放比例,為一個數字,可以帶小數
// maximum-scale 允許用戶最大縮放比例,為一個數字,可以帶小數
// user-scalable 是否允許手動縮放
空白頁基本meta標簽
<!-- 設置縮放 -->
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimal-ui" />
<!-- 可隱藏地址欄,僅針對IOS的Safari(注:IOS7.0版本以后,safari上已看不到效果) -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<!-- 僅針對IOS的Safari頂端狀態條的樣式(可選default/black/black-translucent ) -->
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<!-- IOS中禁用將數字識別為電話號碼/忽略Android平臺中對郵箱地址的識別 -->
<meta name="format-detection"content="telephone=no, email=no" />
其他meta標簽
<!-- 啟用360瀏覽器的極速模式(webkit) -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 針對手持設備優化,主要是針對一些老的不識別viewport的瀏覽器,比如黑莓 -->
<meta name="HandheldFriendly" content="true">
<!-- 微軟的老式瀏覽器 -->
<meta name="MobileOptimized" content="320">
<!-- uc強制豎屏 -->
<meta name="screen-orientation" content="portrait">
<!-- QQ強制豎屏 -->
<meta name="x5-orientation" content="portrait">
<!-- UC強制全屏 -->
<meta name="full-screen" content="yes">
<!-- QQ強制全屏 -->
<meta name="x5-fullscreen" content="true">
<!-- UC應用模式 -->
<meta name="browsermode" content="application">
<!-- QQ應用模式 -->
<meta name="x5-page-mode" content="app">
<!-- windows phone 點擊無高光 -->
<meta name="msapplication-tap-highlight" content="no">
18.移動端如何定義字體font-family?
@ --------------------------------------中文字體的英文名稱
@ 宋體 SimSun
@ 黑體 SimHei
@ 微信雅黑 Microsoft Yahei
@ 微軟正黑體 Microsoft JhengHei
@ 新宋體 NSimSun
@ 新細明體 MingLiU
@ 細明體 MingLiU
@ 標楷體 DFKai-SB
@ 仿宋 FangSong
@ 楷體 KaiTi
@ 仿宋_GB2312 FangSong_GB2312
@ 楷體_GB2312 KaiTi_GB2312
@
@ 說明:中文字體多數使用宋體、雅黑,英文用Helvetica
body { font-family: Microsoft Yahei,SimSun,Helvetica; }
19.打電話發短信寫郵件怎么實現?
// 一、打電話 <a href="tel:0755-10086">打電話給:0755-10086</a> // 二、發短信,winphone系統無效 <a href="sms:10086">發短信給: 10086</a> // 三、寫郵件 <a href="mailto:863139978@qq.com">點擊我發郵件</a> //2.收件地址后添加?cc=開頭,可添加抄送地址(Android存在兼容問題) <a href="mailto:863139978@qq.com?cc=zhangqian0406@yeah.net">點擊我發郵件</a> //3.跟著抄送地址后,寫上&bcc=,可添加密件抄送地址(Android存在兼容問題) <a href="mailto:863139978@qq.com?cc=zhangqian0406@yeah.net&bcc=384900096@qq.com">點擊我發郵件</a> //4.包含多個收件人、抄送、密件抄送人,用分號(;)隔開多個郵件人的地址 <a href="mailto:863139978@qq.com;[url=mailto:384900096@qq.com]384900096@qq.com[/url]">點擊我發郵件</a> //5.包含主題,用?subject= <a href="mailto:863139978@qq.com?subject=郵件主題">點擊我發郵件</a> //6.包含內容,用?body=;如內容包含文本,使用%0A給文本換行 <a href="mailto:863139978@qq.com?body=郵件主題內容%0A騰訊誠信%0A期待您的到來">點擊我發郵件</a> //7.內容包含鏈接,含http(s)://等的文本自動轉化為鏈接 <a href="mailto:863139978@qq.com?body=http://www.baidu.com">點擊我發郵件</a> //8.內容包含圖片(PC不支持) <a href="mailto:863139978@qq.com?body=<img src='images/1.jpg' />">點擊我發郵件</a> //9.完整示例 <a href="mailto:863139978@qq.com;[url=mailto:384900096@qq.com]384900096@qq.com[/url]?cc=zhangqian0406@yeah.net&bcc=993233461@qq.com&subject=[郵件主題]&body=騰訊誠邀您參與%0A%0A[url=http://www.baidu.com]http://www.baidu.com[/url]%0A%0A<img src='images/1.jpg' />">點擊我發郵件</a>
|
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
最近在對《React Native移動開發實戰》一書進行部分修訂和升級。在React Native開發中,免不了會涉及到原生代碼與JS層的消息傳遞等問題,那么React Native究竟是如何實現與原生的互相操作的呢?
原生給JS傳值,主要依靠屬性,也就是通過initialProperties,這個RCTRootView的初始化函數的參數來完成。通過RCTRootView的初始化函數你可以將任意屬性傳遞給React Native應用,參數initialProperties必須是NSDictionary的一個實例。RCTRootView有一個appProperties屬性,修改這個屬性,JS端會調用相應的渲染方法。
使用RCTRootView將React Natvie視圖封裝到原生組件中。RCTRootView是一個UIView容器,承載著React Native應用。同時它也提供了一個聯通原生端和被托管端的接口。
例如有下面一段OC代碼:
下面是JS層的處理:
不管OC中關于initialProperties的名字叫什么,在JS中都是this.props開頭,然后接下來才是key名字。
RCTRootView同樣提供了一個可讀寫的屬性appProperties。在appProperties設置之后,React Native應用將會根據新的屬性重新渲染。當然,只有在新屬性和舊的屬性有更改時更新才會被觸發。
可以隨時更新屬性,但是更新必須在主線程中進行,讀取則可以在任何線程中進行。
.h的文件代碼:
.m的文件代碼:
為了實現RCTBridgeModule協議,你的類需要包含RCT_EXPORT_MODULE()宏。這個宏也可以添加一個參數用來指定在Javascript中訪問這個模塊的名字。如果你不指定,默認就會使用這個Objective-C類的名字。
并且必須明確的聲明要給Javascript導出的方法,否則React Native不會導出任何方法。OC中聲明要給Javascript導出的方法,通過RCT_EXPORT_METHOD()宏來實現。
要用到NativeModules則要引入相應的命名空間import { NativeModules } from ‘react-native’;然后再進行調用CalendarManager.doSomething(‘sdfsdf’,’sdfsdfs’);橋接到Javascript的方法返回值類型必須是void。React Native的橋接操作是異步的,所以要返回結果給Javascript,你必須通過回調或者觸發事件來進行。
說明:第一個參數代表從JavaScript傳過來的數據,第二個參數是回調方法;
RCT_EXPORT_METHOD 支持所有標準JSON類型,包括:
除此以外,任何RCTConvert類支持的的類型也都可以使用(參見RCTConvert了解更多信息)。RCTConvert還提供了一系列輔助函數,用來接收一個JSON值并轉換到原生Objective-C類型或類。例如:
如果需要從iOS原生方法發送數據到JavaScript中,那么使用eventDispatcher。例如:
在JavaScript中可以這樣訂閱事件,通常需要在componentWillUnmount函數中取消事件的訂閱。
用NativeAppEventEmitter.addListener中注冊一個通知,之后再OC中通過bridge.eventDispatcher sendAppEventWithName發送一個通知,這樣就形成了調用關系。
原生給React Native傳參
原生給React Native傳值
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil]; NSArray *imageList = @[@"http://foo.com/bar1.png",
@"http://foo.com/bar2.png"]; NSDictionary *wjyprops = @{@"images" : imageList};
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"ReactNativeProject" initialProperties:wjyprops
launchOptions:launchOptions];
import React, { Component } from 'react'; import {
AppRegistry,
View,
Image,
} from 'react-native'; class ImageBrowserApp extends Component { renderImage(imgURI) { return (
<Image source={{uri: imgURI}} />
);
}
render() { return (
<View>
{this.props.images.map(this.renderImage)}
</View>
);
}
}
AppRegistry.registerComponent('ImageBrowserApp', () => ImageBrowserApp);
{"rootTag":1,"initialProps":{"images":["http://foo.com/bar1.png","http://foo.com/bar2.png"]}}.
使用appProperties進行參數傳遞
NSArray *imageList = @[@"http://foo.com/bar3.png", @"http://foo.com/bar4.png"]; rootView.appProperties = @{@"images" : imageList};
React Native執行原生方法及回調
React Native執行原生方法
#import <Foundation/Foundation.h> #import <RCTBridgeModule.h> @interface wjyTestManager : NSObject<RCTBridgeModule> @end
#import "wjyTestManager.h" @implementation wjyTestManager RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(doSomething:(NSString *)aString withA:(NSString *)a)
{ NSLog(@"%@,%@",aString,a);
} @end
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Alert,
TouchableHighlight,
} from 'react-native';
import {
NativeModules,
NativeAppEventEmitter
} from 'react-native'; var CalendarManager = NativeModules.wjyTestManager; class ReactNativeProject extends Component { render() { return (
<TouchableHighlight onPress={()=>CalendarManager.doSomething('sdfsdf','sdfsdfs')}>
<Text style={styles.text}
>點擊 </Text>
</TouchableHighlight>
);
}
} const styles = StyleSheet.create({
text: {
flex: 1,
marginTop: 55,
fontWeight: 'bold' },
});
AppRegistry.registerComponent('ReactNativeProject', () => ReactNativeProject);
傳參并回調
RCT_EXPORT_METHOD(testCallbackEvent:(NSDictionary *)dictionary callback:(RCTResponseSenderBlock)callback)
{ NSLog(@"當前名字為:%@",dictionary); NSArray *events=@[@"callback ", @"test ", @" array"];
callback(@[[NSNull null],events]);
}
JS層代碼:
import {
NativeModules,
NativeAppEventEmitter
} from 'react-native'; var CalendarManager = NativeModules.wjyTestManager; class ReactNativeProject extends Component { render() { return (
<TouchableHighlight onPress={()=>{CalendarManager.testCallbackEvent(
{'name':'good','description':'http://www.lcode.org'},
(error,events)=>{ if(error){
console.error(error);
}else{
this.setState({events:events});
}
})}}
>
<Text style={styles.text}
>點擊 </Text>
</TouchableHighlight>
);
}
}
參數類型說明
#import "RCTConvert.h" #import "RCTBridge.h" #import "RCTEventDispatcher.h" // 對外提供調用方法,為了演示事件傳入屬性字段 RCT_EXPORT_METHOD(testDictionaryEvent:(NSString *)name details:(NSDictionary *) dictionary)
{ NSString *location = [RCTConvert NSString:dictionary[@"thing"]]; NSDate *time = [RCTConvert NSDate:dictionary[@"time"]]; NSString *description=[RCTConvert NSString:dictionary[@"description"]]; NSString *info = [NSString stringWithFormat:@"Test: %@\nFor: %@\nTestTime: %@\nDescription: %@",name,location,time,description]; NSLog(@"%@", info);
}
iOS原生訪問React Native
#import "RCTBridge.h" #import "RCTEventDispatcher.h" @implementation CalendarManager @synthesize bridge = _bridge; // 進行設置發送事件通知給JavaScript端 - (void)calendarEventReminderReceived:(NSNotification *)notification
{ NSString *name = [notification userInfo][@"name"];
[self.bridge.eventDispatcher sendAppEventWithName:@"EventReminder" body:@{@"name": name}];
} @end
import { NativeAppEventEmitter } from 'react-native';
var subscription = NativeAppEventEmitter.addListener( 'EventReminder',
(reminder) => console.log(reminder.name)
); ... // 千萬不要忘記忘記取消訂閱, 通常在componentWillUnmount函數中實現。
subscription.remove();
素材類網站
Unsplash是一個分享免費高質量照片的網站,照片分辨率都挺大,而且都是真實的攝影師作品,圖片多是風景和靜物:https://unsplash.com/
插件類網站
jq22,分享jQuery插件和提供各種jQuery的詳細使用方法,在線預覽,jQuery插件下載及教程:http://www.jq22.com/
http://www.htmleaf.com/ 這個網站與上一個網站類似,也提供了大量的jQuery插件。
layui,這是一個強大的模塊化前端框架:http://www.layui.com/
H-ui,端框架,一個輕量級前端框架,簡單免費,兼容性好,服務中國網站:http://www.h-ui.net/index.shtml
字體類網站
有字庫,一個免下載字體,直接在線引用字體的網站:http://www.youziku.com/onlinefont/index
PS字體庫,包含了幾乎所有類型的字體,下載好安裝,PS中就可以使用了:http://www.psjia.com/pssc/fontxz/list_18_3.html
圖標類網站
iconfont,這是阿里巴巴旗下的圖標庫網站,直接搜索關鍵詞就可以找到大批的圖標。下載圖標的時候我們還可以選擇顏色、大小、格式,根據自己的需要下載就好了:http://www.iconfont.cn/plus
easyicon,這也是一個非常有名的圖標庫,與上面那個不同的是,這里的圖標不是單一顏色的,而是設計好的顏色。下載圖標也很簡單,直接點擊對應圖標上面的格式就可以下載:http://www.easyicon.net/iconsearch/ios/
奧森圖標(Font Awesome),提供豐富的矢量字體圖標—通過CSS可以任意控制所有圖標的大小 ,顏色,陰影:http://www.thinkcmf.com/font/search.html
配色類網站
http://colorhunt.co,這個網站給我們提供了很多的配色方案,我們直接使用就OK了。
使用方法也很簡單,鼠標移動到對應的顏色上,我們就可以看到顏色的十六進制碼,復制這個顏色到工具里就可以使用了。
https://webgradients.com/, 180種漸變方案供你選擇,還可以直接復制CSS樣式應用到網頁中。
adobe,這個是Adobe公司出的,他提供了多種配色方案。我們點擊圓盤中間的點,就可以調整出我們想要的配色方案:https://color.adobe.com/zh/create/color-wheel
http://www.colorhunter.com/,這是一個提取現有圖片配色方案的工具。我們上傳一張圖片,它就會幫我們把圖片的配色提取出來供我們使用。
bootcss,這個網站是為WEB設計,開發中經常用到的安全色。網站內列出了顏色的十六進制碼和RGB碼,復制粘貼就可以了:http://www.bootcss.com/p/websafecolors/
sioe,這是一個在線RGB和十六進制顏色碼轉換工具。在對應的位置填入十六進制代碼,點擊轉換,我們就可以獲取到RGB顏色的代碼了:http://www.sioe.cn/yingyong/yanse-rgb-16/
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
js中構造函數的幾種繼承模式淺析
一、原型鏈模式繼承
利用原型讓一個引用類型繼承另一個引用類型的屬性和方法 。
用的最多。
缺點:不可傳參,不可多繼承。
-
function People(name, age) {//添加公有屬性
-
name = name || 'xiaolan';
-
age = age || 18;
-
this.name = name;
-
this.age = age;
-
}//創建一個名為People的類
-
People.prototype.eat = function() {//添加私有屬性
-
console.log(this.name + '賊能吃');
-
}
-
function Cat(color) {//創建一個名為Cat的類
-
this.color = color;
-
}
-
Cat.prototype = new People('小叮當', 200);//實例化一個People類,并賦值給Cat類的原型鏈
-
var cat = new Cat('藍白色')
-
console.log(cat.name)//'小叮當'
-
cat.eat();//'小叮當賊能吃'
二、混合模式繼承
用call的方法只能繼承私有屬性,所以再加一遍一遍原型鏈模式繼承,原型鏈模式繼承又把私有屬性和公有屬性都繼承了一遍。
-
function People(name, age) { //創建一個父級People類
-
name = name || 'xiaolan';
-
age = age || 18;
-
this.name = name;
-
this.age = age;
-
}
-
People.prototype.eat = function() {
-
console.log(this.name + '賊能吃');
-
}
-
-
function Cat(color, name, age) {
-
this.color = color;
-
People.call(this, name, age); //通過call的形式繼承
-
//通過call(this),將People的指向改為Cat的實例
-
}
-
var cat = new Cat('藍白色', '小叮當', 1);
-
console.log(cat.name);//'小叮當'
-
cat.eat();//報錯,
-
//繼承不了公有屬性,所以cat.eat()會報錯;
為了繼承公有屬性,用原型鏈模式在把公有屬性和方法繼承過來,
-
function People(name, age) { //創建一個父級People類
-
name = name || 'xiaolan';
-
age = age || 18;
-
this.name = name;
-
this.age = age;
-
}
-
People.prototype.eat = function() {
-
console.log(this.name + '賊能吃');
-
}
-
-
function Cat(color, name, age) {
-
this.color = color;
-
People.call(this, name, age); //通過call的形式繼承
-
//通過call(this),將People的指向改為Cat的實例
-
}
-
Cat.prototype = new People()
-
var cat = new Cat('藍白色', '小叮當', 200)
-
console.log(cat)
-
console.log(cat.name); //'小叮當',在原型鏈繼承的時候,就近原則,cat.name 先找到'小叮當',就不往下找了
-
cat.eat(); //'小叮當賊能吃'
三、拷貝繼承
優點:可以多繼承,可傳參;
缺點:浪費資源,不能判斷父級;
-
function People(name, age) { //創建一個父級People類
-
name = name || 'xiaolan';
-
age = age || 18;
-
this.name = name;
-
this.age = age;
-
}
-
People.prototype.eat = function() {
-
console.log(this.name + '賊能吃');
-
}
-
-
function Cat(color, name, age) {
-
this.color = color;
-
var people = new People(name, age) //實例化一個People類
-
for (let i in people) {
-
this[i] = people[i]; //將people中的可枚舉屬性和方法遍歷并附給Cat類,公有屬性和私有屬性都是可枚舉屬性;
-
}
-
}
-
var cat = new Cat('藍白色', '小叮當', 2);
-
console.log(cat.name); //小叮當
-
cat.eat(); //小叮當賊能吃
四、寄生組合方式繼承
優點:私有屬性和公有屬性都單獨繼承,可以傳參;
私有屬性可以多繼承,公有屬性不可多繼承;
-
function People(name, age) {
-
name = name || 'xiaolan';
-
age = age || 18;
-
this.name = name;
-
this.age = age;
-
}
-
People.prototype.eat = function() {
-
console.log(this.name + '賊能吃');
-
}
-
-
function Cat(color, name, age) {
-
this.color = color;
-
People.call(this, name, age) //用call的形式把私有屬性繼承過來
-
}
-
-
function Fn() {} //創建一個中間構造函數,用來接收People的公有屬性,為了防止創建實例Cat實例是影響原來的people構造函數
-
Fn.prototype = People.prototype;
-
Cat.prototype = new Fn(); //將中間構造函數Fn繼承people的公有屬性傳給Cat的原型鏈
-
Cat.prototype.constructor = Cat; //由于上一步重置了Cat原型鏈的constructor屬性,所以要重新給賦回來;
-
var cat = new Cat('藍白色', '小叮當', 3);
-
console.log(cat.name); //'小叮當'
-
cat.eat() //'小叮當賊能吃
注:若有不嚴謹與錯誤的地方,請多指教!
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
問題總結 https://github.com/vuejs-templates/webpack/issues/260
首先npm install --save babel-polyfill
然后在main.js
中的最前面引入babel-polyfill
import 'babel-polyfill'
在index.html 加入以下代碼(非必須)
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
在config中的webpack.base.conf.js
中,修改編譯配置
-
entry:{
-
app:['babel-polyfill','./src/main.js']
-
}
當然,如果你只用到了 axios
對 promise
進行兼容,可以只用 es6-promise
npm install es6-promise --save
在 main.js
中的最前面 引入
import 'es6-promise/auto'
那么,就有一個問題了,build之后的dist文件只有放在服務器上才能查看,但本地如何查看呢,參考一下配置
修改config文件夾中的index.js文件,將build對象中的打包路徑,'/
‘改為'./'
,由絕對路徑改為相對路徑,建議將sourceMap
改為false
,編譯的時候會快一點
build: { assetsPublicPath: './', productionSourceMap: false, },
修改完之后,重新 npm run build ,得到新的dist文件夾
然后進入dist文件夾
cd dist
全局安裝簡易node服務器
npm install http-server -g
啟動簡易node服務器
http-server
出現如下圖所示,就代表你的服務器啟動成功了,那你也能在5000端口查看編譯打包后的項目了,可以在ie瀏覽器中直接測試了
IE在處理日期的時候,不支持-支持/的日期方式 如 2017-01-01應該
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
Promise 是異步編程的一種解決方案,比傳統的解決方案–回調函數和事件--更合理和更強大。它由社區最早提出和實現,ES6將其寫進了語言標準,統一了語法,原生提供了Promise
所謂Promise ,簡單說就是一個容器,里面保存著某個未來才回結束的事件(通常是一個異步操作)的結果。從語法上說,Promise是一個對象,從它可以獲取異步操作的消息。
三種狀態:
狀態改變:
這兩種情況只要發生,狀態就凝固了,不會再變了,這時就稱為resolved(已定型
基本用法
ES6規定,Promise對象是一個構造函數,用來生成Promise實例
Promise的源碼分析:
曾幾何時,我們的代碼是這樣的,為了拿到回調的結果,不得不
終于,我們的
首先我們要知道自己手寫一個
我們先聲明一個類,叫做
那么接下來我會分析上面代碼的作用,原理
then方法是
這里主要做了將構造器中resolve和reject的結果傳入
之前我們只是處理了同步情況下的Promise,簡而言之所有操作都沒有異步的成分在內。那么如果是異步該怎么辦?
最早處理異步的方法就是callback,就相當于我讓你幫我掃地,我會在給你發起任務時給你一個手機,之后我做自己的事情去,不用等你,等你掃完地就會打手機給我,誒,我就知道了地掃完了。這個手機就是callback,回調函數。
首先我們需要改一下構造器里的代碼,分別添加兩個回調函數的數組,分別對應成功回調和失敗回調。他們的作用是當成功執行resolve或reject時,執行callback。
然后是then需要多加一個狀態判斷,當Promise中是異步操作時,需要在我們之前定義的回調函數數組中添加一個回調函數。
ok!大功告成,異步已經解決了
這也是
一下子多了很多方法,不用怕,我會一一解釋
那就讓我們來看看這個
它的作用是用來將onFufilled的返回值進行判斷取值處理,把最后獲得的值放入最外面那層的
我們現在已經基本完成了Promise的then方法,那么現在我們需要看看他的其他方法。
相信大家都知道catch這個方法是用來捕獲Promise中的reject的值,也就是相當于then方法中的onRejected回調函數,那么問題就解決了。我們來看代碼。
該方法是掛在Promise原型上的方法。當我們調用catch傳callback的時候,就相當于是調用了then方法。
大家一定都看到過
這兩個方法是直接可以通過class調用的,原理就是返回一個內部是resolve或reject的Promise對象。
all方法可以說是Promise中很常用的方法了,它的作用就是將一個數組的Promise對象放在其中,當全部resolve的時候就會執行then方法,當有一個reject的時候就會執行catch,并且他們的結果也是按著數組中的順序來排放的,那么我們來實現一下。
其原理就是將參數中的數組取出遍歷,每當執行成功都會執行
race方法雖然不常用,但是在Promise方法中也是一個能用得上的方法,它的作用是將一個
原理大家應該看懂了,很簡單,就是遍歷數組執行Promise,如果有一個
語法糖這三個字大家一定很熟悉,作為一個很Swag的前端工程師,對async/await這對兄弟肯定很熟悉,沒錯他們就是generator的語法糖。而我們這里要講的語法糖是Promise的。
什么作用呢?看下面代碼你就知道了
沒錯,我們可以方便的去調用他語法糖defer中的
Promise 的含義
Promise 對象的狀態不受外界影響
Promise對象的狀態改變,只有兩種可能:
resolve
函數的作用是,將Promise對象的狀態從“未完成”變為“成功”(即從 pending
變為 resolved
),在異步操作成功時調用,并將異步操作的結果,作為參數傳遞出去;
reject
函數的作用是,將Promise對象的狀態從“未完成”變為“失敗”(即從 pending
變為 rejected
),在異步操作失敗時調用,并將異步操作報出的錯誤,作為參數傳遞出去。
1.回調地獄
callback hell
,這種環環相扣的代碼可以說是相當惡心了
蓋世英雄
出現了,他身披金甲圣衣、駕著七彩祥云。好吧打岔兒了,沒錯他就是我們的Promise
,那讓我們來看看用了Promise
之后,上面的代碼會變成什么樣吧
2.重點開始,小眼睛都看過來
2.1 Promise/A+
Promise
,應該怎么去寫,誰來告訴我們怎么寫,需要遵循什么樣的規則。當然這些你都不用擔心,其實業界都是通過一個規則指標來生產Promise
的。讓我們來看看是什么東西。傳送門?Promise/A+
2.2 constructor
Promise
,里面是構造函數。如果es6還有問題的可以去阮大大的博客上學習一下(傳送門?es6)
executor:
這是實例Promise
對象時在構造器中傳入的參數,一般是一個function(resolve,reject){}
status:``Promise
的狀態,一開始是默認的pendding狀態,每當調用道resolve和reject方法時,就會改變其值,在后面的then方法中會用到
value:
resolve回調成功后,調用resolve方法里面的參數值
reason:
reject回調成功后,調用reject方法里面的參數值
resolve:
聲明resolve方法在構造器內,通過傳入的executor方法傳入其中,用以給使用者回調
reject:
聲明reject方法在構造器內,通過傳入的executor方法傳入其中,用以給使用者回調
2.3 then
Promise
中最為重要的方法,他的用法大家都應該已經知道,就是將Promise
中的resolve或者reject的結果拿到,那么我們就能知道這里的then方法需要兩個參數,成功回調和失敗回調,上代碼!
onFufilled
和onRejected
中,注意這兩個是使用者傳入的參數,是個方法。所以你以為這么簡單就完了?要想更Swag
的應對各種場景,我們必須得再完善。繼續往下走!
3.異步的Promise
3.1 callback?。。?!
3.2 resolvePromise
Promise
中的重頭戲,我來介紹一下,我們在用Promise的時候可能會發現,當then函數中return了一個值,我們可以繼續then下去,不過是什么值,都能在下一個then中獲取,還有,當我們不在then中放入參數,例:promise.then().then()
,那么其后面的then依舊可以得到之前then返回的值,可能你現在想很迷惑。讓我來解開你心中的憂愁,follow me。
Promise
?:首先我們要注意的一點是,then有返回值,then了之后還能在then,那就說明之前的then返回的必然是個Promise
。
setTimeout
?:因為Promise本身是一個異步方法,屬于微任務一列,必須得在執行棧執行完了在去取他的值,所以所有的返回值都得包一層異步setTimeout。
resolvePromise
是什么?:這其實是官方Promise/A+的需求。因為你的then可以返回任何職,當然包括Promise
對象,而如果是Promise
對象,我們就需要將他拆解,直到它不是一個Promise
對象,取其中的值。
resolvePromise
到底長啥樣。
Promise
的resolve函數中。
promise2
(then函數返回的Promise對象),x
(onFufilled函數的返回值),resolve、reject
(最外層的Promise上的resolve和reject)。
promise2
和x
?:首先在Promise/A+中寫了需要判斷這兩者如果相等,需要拋出異常,我就來解釋一下為什么,如果這兩者相等,我們可以看下下面的例子,第一次p2是p1.then出來的結果是個Promise
對象,這個Promise
對象在被創建的時候調用了resolvePromise(promise2,x,resolve,reject)函數,又因為x等于其本身,是個Promise
,就需要then方法遞歸它,直到他不是Promise
對象,但是x(p2)的結果還在等待,他卻想執行自己的then方法,就會導致等待。
resolvePromise
函數已經resolve或者reject了,那就不需要在執行下面的resolce或者reject。
resolvePromise
函數?:相信細心的人已經發現了,我這里使用了遞歸調用法,首先這是Promise/A+中要求的,其次是業務場景的需求,當我們碰到那種Promise的resolve里的Promise的resolve里又包了一個Promise的話,就需要遞歸取值,直到x不是Promise對象。
4.完善Promise
4.1 catch
4.2 resolve/reject
Promise.resolve()、Promise.reject()
這兩種用法,它們的作用其實就是返回一個Promise對象,我們來實現一下。
4.3 all
processData
方法,processData
方法就是用來記錄每個Promise的值和它對應的下標,當執行的次數等于數組長度時就會執行resolve,把arr的值給then。這里會有一個坑,如果你是通過arr數組的長度來判斷他是否應該resolve的話就會出錯,為什么呢?因為js數組的特性,導致如果先出來的是1位置上的值進arr,那么0位置上也會多一個空的值,所以不合理。
4.4 race
Promise
數組放入race中,哪個先執行完,race就直接執行完,并從then中取值。我們來實現一下吧。
Promise
執行成功就resolve。
Promise語法糖 deferred
Promise
對象。那么它還有沒有另外的方法呢?答案是有的。我們需要在全局上安裝promises-aplus-tests插件npm i promises-aplus-tests -g
,再輸入promises-aplus-tests [js文件名] 即可驗證你的Promise的規范。
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里
通常當用戶打開一個資源的
對于壓縮格式的文件(
對于瀏覽器這種行為,一般情況下是可以接受的,因為用戶可以在瀏覽器顯示文件后將文件保存到電腦中,但是一些情況下用戶可能希望文件直接被下載而不是在瀏覽器中被打開,比如有時候用戶想去下載一個歌曲,但是瀏覽器可能回去播放該音頻。那么怎么讓瀏覽器強制去下載文件要怎么做呢
瀏覽器會根據資源類型去判斷是否支持,如果支持時會嘗試去在頁面上展示該資源。瀏覽器判斷資源類型是根據返回頭
在HTTP場景中,
因此當我們希望該資源被直接下載時候,我們可以設置返回頭
這里設置名稱時候,要注意下
瀏覽器既然定義了該行為,根據瀏覽器的不同用戶可能在設置頁面去配置某些格式的文件是否希望瀏覽器去展示該文件。一些有爭議的情況下,你也可以提示用戶自己根據需求去設置這些參數。
url
,如果瀏覽器支持這個格式的文件的情況下,瀏覽器會嘗試去再頁面里展示它而不是直接下載。例如一張圖片(jpg, png, gif等
),幾乎所有瀏覽器都會去將圖片在瀏覽器里面展示。
zip, tar, gzip等
)瀏覽器總是會直接去下載它們,另外一些格式的文件,根據瀏覽器的不同也會有差異的處理方法,例如Microsoft Word
文件(doc, docx
)在ie
瀏覽器下通常會在瀏覽器中展示,但是其他瀏覽器幾乎都會直接下載它,同樣的對于PDF
文件chrome
有自己的pdf 轉換器
它會嘗試去在瀏覽器上展示該文件。
強制下載文件
a標簽的download屬性
html5
中 a
標簽新增了 download
屬性,該屬性指示瀏覽器下載url
的內容而不是導航到url
,因此如果配置了此屬性用戶會直接下載url
的內容。作為開發如果想直接觸發該事件我們可以直接用代碼模擬a標簽和點擊事件
download
屬性只在同域時候有效,當跨域請求時候該屬性將會被忽略。
改變資源格式
Content-Type
的值,因此一方面我們在服務端可以設置返回頭字段為文件流'Content-Type': 'application/octet-stream'
,或者根據一些具體資源直接壓縮后傳輸,瀏覽器不能分析zip
之類的壓縮文件所以會直接去下載它們。
配置Content-Disposition
Content-Disposition
消息頭指示回復的內容該以何種形式展示,是以內聯的形式(即網頁或者頁面的一部分),還是以附件的形式下載并保存到本地。
inline
默認參數表示消息體會以頁面的一部分或者整個頁面的形式展示。
attachment
消息體應該被下載到本地,將參數filename
的值預填為下載后的文件名
Content-Disposition
的值為attachment
。
filename
的編碼格式。
用戶自己在瀏覽器設置
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
藍藍設計的小編 http://www.syprn.cn