[toc]
## 作用
保證頁面打開的速度
一般來說3s之內如果首頁打不開就被稱之為**死亡頁面**了。
## 原理
>1)對于首屏內容中的圖片:首先給對應的區域一張默認圖片占著位置(默認圖需要灰常小,一般可以維持在5kb以內),當首屏內容都加載完成后(或則也可以給一個延遲的時間),我們才開始加載真實的圖片
>2)對于其它屏中的圖片,也是給一張默認的圖片占位,當滾動條滾動到對應區域的時候,我們再開始加載真實的圖片
擴展:數據的異步加載,開始只把前兩屏的數據加載綁定出來,后面的數據不進行處理,當頁面滾動到對應區域的時候再重新請求數據然后綁定渲染數據。
## 實現
```
.banner {
//當圖片還沒加載時以默認圖片顯示
background:url() no-repeat center center #elelel;
}
.banner img{
display:none; //在開始的時候IMG的SRC屬性沒有地址,這樣的話在IE瀏覽器中會顯示一張碎圖,不美觀,所以我們讓其默認是隱藏的,當真實圖片加載完成后顯示
width:100%;
height:100%;
}
```
```
<div class="banner" id="banner">
// trueImg是當前IMG標簽的自定義屬性,存儲的是真實圖片的地址
<img src="" trueImg="img/jd.jpg"/>
</div>
```
```
var banner = document.getElementById("banner"),imgFir = banner.getElemetsByTagName("img")[0];
//window.onload
window.setTimeout(function(){
imgFir.src = imgFir.getAttribute("trueImg");
imgFir.style.display = "block";
},500)
```
以上處理還是不完整的:如果我們獲取的真實圖片地址是錯誤的,當賦值給IMG的SRC屬性的時候,不僅控制臺會報錯,而且頁面中會出現碎圖或則叉子圖,影響用戶體驗
獲取圖片的地址,驗證地址的有效性,是有效的才賦值,不是有效的不進行賦值處理
```
var oImg = document.createElement("img");
var oImg = new Image; //等同有上面,都是創建一個臨時的IMG標簽
oImg.src = imgFir.getAttribute("trueImg");
oImg.onload = function(){ //當圖片能夠正常加載
imgFir.src = this.src;
imgFir.style.display = "block";
oImg = null;
}
```
## 單張圖片加載

```
window.onscroll = function(){
var A = banner.offsetHeight + banner.offsetTop;
}
```

這樣有個問題會被加載多次
為已加載的圖片做一個標識

這樣仍然有問題的是,若圖片不存在,隨著滾動,會反復執行事件函數(進不到.onload)中,
So應該把`isLoad`的設置放在`onload`外

## 多張圖片加載
1、 ajax異步獲取
2、 字符串拼接,將數據和模板綁定
3、 循環判斷并加載
```
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<!--移動端就這樣放這-->
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
<style>
*{ margin: 0; padding: 0; }
ul{ list-style: none; padding: 10px; }
ul li{ position: relative; height: 60px; padding: 10px; border-bottom: 1px dashed #ccc; }
ul li>div:nth-child(1){
position: absolute;
left: 0;
top: 10px;
width: 60px;
height: 60px;
background: url("images/default.jpg") no-repeat center;
background-size: cover; /*覆蓋*/
}
ul li>div:nth-child(1) img{
display: none;
width: 100%;
height: 100%;
opacity: 0;
filter: alpha(opacity=0);
}
ul li>div:last-child{
padding: 5px;
box-sizing: border-box;
overflow: hidden;
height: 60px;
_background: lightblue;
margin-left: 70px;
}
ul li>div:last-child h2{
line-height: 20px;
font-size: 14px;
/*標題省略號*/
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
ul li>div:last-child p{
font-size: 12px;
color: #999;
}
</style>
</head>
<body>
<ul id="newsList">
<li>
<div><img src="" alt=""/></div>
<div>
<h2>標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題標題</h2>
<p>描述描述描述描述描述描述描述描述描述描述描述</p>
</div>
</li>
<!--<li></li>
<li></li>
<li></li>
<li></li>-->
</ul>
</body>
</html>
<script src="utils.js"></script>
<script>
/*獲取數據*/
//ajax
var jsonData = null; //這會還沒有數據
var oUl = document.getElementById('newsList');
var imgList = oUl.getElementsByTagName('img'); //數據還沒做呢
~function (){
var xhr = new XMLHttpRequest();
xhr.open('get','jsonData.txt?_'+Math.random(),false); //同步獲取 可以避免瀏覽器的緩存問題,上一次獲取來的數據,如果下一次地址沒變我默認從本地緩存讀取。不在去服務器去請求了 url ? 問號后面的是參數集合 集合和集合用&符號分開 ?set=1 &weight=80
xhr.onreadystatechange = function (){
if(xhr.readyState == 4 && xhr.status == 200){ // reg = /^2\d{2}$/ 304 開頭代表你從本地緩存讀取過來的 404 5開頭代表服務端錯誤
//jsonData = xhr.responseText; //
jsonData = utils.jsonParse(xhr.responseText); //把文本轉化為json格式的對象
}
}
xhr.send(null); //發送
}();
console.log(jsonData); //成功獲取到數據
//數據綁定,把json中的數據,我們這次用字符串拼接的方式動態綁定
~function (){
if(jsonData){ //首先判斷我們數據已經成功獲取
//循環拼接ul里面的字符串
var str = '';
for(var i=0; i<jsonData.length; i++){
var cur = jsonData[i];
str += '<li>';
str += '<div><img src="" trueSrc="' + cur.img + '" /></div>';
str += '<div><h2>'+ cur.title +'</h2><p>'+ cur.desc+'</p></div>';
str += '</li>';
}
oUl.innerHTML = str; //把拼接好的字符串賦值給列表的innerHTML
}
}();
//圖片延遲加載 首先先實現單張圖片延遲加載
function imgDelayLoad(curImg){ //??這個函數要被用多少次,jsonData.length
//
if(curImg.isLoad){
return;
}
var tempImg = new Image();
tempImg.src = curImg.getAttribute('trueSrc'); //臨時的圖片就去加載真是的圖片資源了
tempImg.onload = function (){
curImg.src = this.src; //說明已經加載成功了,我們這個圖片的資源路徑是有效的。
curImg.style.display = 'block';
tempImg = null;
}
curImg.isLoad = true; //只要你曾經加載過,不管是否成功我都沒有必要去加載第二次了
}
//多張圖片延遲加載
// 首先獲取我們所有的圖片集合
function allImgDelay(){
for(var i=0; i<imgList.length; i++){
//給每一個圖片延遲加載
var curImg = imgList[i];
if (curImg.isLoad) continue; //優化 曾經加載過的圖片就不需要再延遲加載了
var browerBottomDisBodyTop = utils.getWin('clientHeight') + utils.getWin('scrollTop'); //瀏覽器底部距離body頂端
var imgParentBottomDisBodyTop = utils.offset(curImg.parentNode).top + curImg.parentNode.offsetHeight; //圖片父親容器底部距離body頂端
if(browerBottomDisBodyTop>imgParentBottomDisBodyTop){ //判斷這個圖片是否已經出現在了瀏覽器的可視窗口內, 我們要判斷img這個圖片的parentNode
imgDelayLoad(curImg); //分別多次調用單個圖片延遲加載
fadeIn(curImg); //淡入的方式
}
}
}
window.setTimeout(allImgDelay,1000); //第一屏圖片延遲加載,第一屏已經完全出現在可視窗口內,所以就需要圖片延遲加載
window.onscroll = allImgDelay; //滾輪的時候也需要圖片延遲加載
//處理多張
function fadeIn(curImg){ //淡入
var duration = 1000; //這么長的時間間隔完成淡入效果
var target = 1; //淡入效果變化的透明度區間,從0運動到1
var interval = 10; //執行定時器的時間間隔
var step = (target/duration)*interval; //每一次執行定時器需要加上的步長
var timer = window.setInterval(function (){
if(curOpacity >= target){ //說明已經運動到了終點,停止定時器
window.clearInterval(timer);
//賦值終點的動作 把target的值賦值給當前元素的樣式
return;
}
debugger;
var curOpacity = utils.getCss(curImg,'opacity'); //賦值之前需要先獲取,因為要在當前的基礎上去累加步長
curOpacity += step;
curImg.style.opacity = curOpacity; //把已經累加好的重新賦值給樣式這樣才能有每次淡入一點的效果
curImg.style.filter = 'alpha(opacity='+ curOpacity*100+ ')'; //兼容問題的處理
},interval);
}
</script>
```
- 空白目錄
- window
- location
- history
- DOM
- 什么是DOM
- JS盒子模型
- 13個核心屬性
- DOM優化
- 回流與重繪
- 未整理
- 文檔碎片
- DOM映射機制
- DOM庫封裝
- 事件
- 功能組件
- table
- 圖片延遲加載
- 跑馬燈
- 回到頂部
- 選項卡
- 鼠標跟隨
- 放大鏡
- 搜索
- 多級菜單
- 拖拽
- 瀑布流
- 數據類型的核心操作原理
- 變量提升
- 閉包(scope)
- this
- 練習題
- 各種數據類型下的常用方法
- JSON
- 數組
- object
- oop
- 單例模式
- 高級單例模式
- JS中常用的內置類
- 基于面向對象創建數據值
- 原型和原型鏈
- 可枚舉和不可枚舉
- Object.create
- 繼承的六種方式
- ES6下一代js標準
- babel
- 箭頭函數
- 對象
- es6勉強筆記
- 流程控制
- switch
- Ajax
- eval和()括號表達式
- 異常信息捕獲
- 邏輯與和或以及前后自增
- JS中的異步編程思想
- 上云
- 優化技巧
- 跨域與JSONP
- 其它跨域相關問題
- console
- HTML、XHTML、XML
- jQuery
- zepto
- 方法重寫和方法重載
- 移動端
- 響應式布局開發基礎
- 項目一:創意簡歷