【小技巧】基于vue+swiper實(shí)現(xiàn)圖片庫列表點(diǎn)擊查看大圖,可左右切換(事件委托、動態(tài)數(shù)組肴裙、懶加載趾唱、緩存、節(jié)流防抖)

最近接到一個需求蜻懦,實(shí)現(xiàn)起來很簡單甜癞,但是考慮到性能問題,需要花一些技巧宛乃。

頁面性能優(yōu)化悠咱,分別應(yīng)用到:
事件委托蒸辆、動態(tài)數(shù)組、懶加載析既、緩存躬贡、節(jié)流防抖

場景和需求:
移動端一個圖庫列表頁,幾百張甚至幾千張圖片的列表展示
點(diǎn)擊其中的一張圖片眼坏,可以預(yù)覽大圖拂玻,左右切換查看所有其他圖片的大圖

- 第一部分:

問題:點(diǎn)擊事件,如果每張圖的標(biāo)簽都綁定了事件宰译,在移動端檐蚜,性能很糟糕。

解決辦法:事件委托沿侈。

HTML結(jié)構(gòu):

<ul class="photo-items"  @click="previewPhoto" id='photo-list'>
      <li v-for="(item,index) in items" class="photo-item"  :data-index="index">
           <img :src="item.srcUrl"/>
      </li>
</ul>
previewPhoto(ev){
   let oUl = document.getElementById('photo-list');
   let ev = ev || window.event;
   let target = ev.target || ev.srcElement;
   while(target !== oUl ){
        //遞歸調(diào)用闯第,使當(dāng)前點(diǎn)擊對象指定到li上
        if(target.tagName.toLowerCase() == 'li'){
             const index = parseInt(target.dataset.index)
             break;
        }
       target = target.parentNode;
    }
},

事件委托參考文章:https://www.cnblogs.com/liugang-vip/p/5616484.html

- 第二部分:

問題:使用swiper,左右切換圖片缀拭,
如果需要查看幾百張圖片咳短,就要生成幾百個swiper-slide,對性能來說也是一件很糟糕的事情智厌。

如圖:


image.png

解決辦法:使渲染swiper的數(shù)組永遠(yuǎn)只有三張圖片诲泌,每次切換盲赊,根據(jù)索引讓數(shù)組的三張圖片變一次铣鹏。

<swiper :options="swiperOption" ref="mySwiper" >
        <swiper-slide  v-for="(item,index) in swiperList" :key="index">
             <img :src="item.srcUrl"/>
        </swiper-slide>
</swiper>
image.png
computed: {
  swiperPicList(){
   if(this.items.length > 0){  //圖片數(shù)組如果不為空
        //curIndex表示當(dāng)前查看的圖片索引
        if(this.curIndex == 0){  //當(dāng)前圖片為第一張時候,返回的數(shù)組
            return [
               {srcUrl: this.items[this.curIndex].srcUrl},
               {srcUrl: this.items[this.curIndex + 1].srcUrl},
            ] 
        }else if(this.curIndex == (this.items.length - 1)){ //當(dāng)前圖片為最后一張時候哀蘑,返回的數(shù)組
             return [
                {srcUrl: this.items[this.curIndex-2].srcUrl},
                {srcUrl: this.items[this.curIndex-1].srcUrl},
                {srcUrl: this.items[this.curIndex].srcUrl},
              ]
         }else{ 
             return [
                {srcUrl: this.items[this.curIndex - 1].srcUrl},
                {srcUrl: this.items[this.curIndex].srcUrl},
                {srcUrl: this.items[this.curIndex + 1].srcUrl},
              ] 
         }
     }
  },
}
image.png

為什么是三張圖诚卸?

因?yàn)閟wiper,有兩個屬性绘迁,當(dāng)滑動到第一張的時候isBeginning為true合溺,這可以當(dāng)做用戶向左滑的判斷,當(dāng)滑動到最后一張的時候isEnd為true缀台,同理可以當(dāng)做用戶向右滑動的判斷棠赛。

[
{srcUrl: this.items[this.curIndex - 1].srcUrl},//當(dāng)前圖片前一張
{srcUrl: this.items[this.curIndex].srcUrl},//當(dāng)前圖片
{srcUrl: this.items[this.curIndex + 1].srcUrl},//當(dāng)前圖片后一張
] 

然后使當(dāng)前索引的圖片永遠(yuǎn)在數(shù)組swiperPicList中間,
1膛腐、向左滑動的時候睛约,curIndex--,向右滑動的時候 curIndex++

但是對于swiper中間選中項(xiàng)向左滑到第一張哲身,第一張會變成選中項(xiàng)辩涝,用戶看到的其實(shí)是數(shù)組第一張圖。向右同理勘天。

所以需要使用swiper方法this.swiper.slideTo(1,0, false)怔揩,使得每次滑動之后捉邢,swiper都切換到第二個為選中項(xiàng),這樣用戶看到是就是數(shù)組的中間項(xiàng)商膊。

參考API:
mySwiper.slideTo(index, speed, runCallbacks)
Swiper切換到指定slide伏伐。
index:必選,num晕拆,指定將要切換到的slide的索引秘案。
speed:可選,num(單位ms)潦匈,切換速度
runCallbacks: 可選阱高,boolean,設(shè)置為false時不會觸發(fā)transition回調(diào)函數(shù)茬缩。

除了是第一張和最后一張的時候做特殊處理赤惊。

watch:{
   curIndex(curIndex){
       if(curIndex == 0){ 
         //當(dāng)滑動到第一張圖片的時候,返回的數(shù)組是兩張圖凰锡,
         //slideTo的index應(yīng)該為0未舟,跳轉(zhuǎn)到第一張圖。
         this.swiper.slideTo(0,0, false);
       }else if (this.curIndex == (this.items.length-1)){
         //當(dāng)滑動到最后一張圖片的時候掂为,返回數(shù)組是三張圖
         //slideTo的index應(yīng)該為2裕膀,跳轉(zhuǎn)到第三張圖。
         this.swiper.slideTo(2,10, false); 
      }else {
         this.swiper.slideTo(1,0, false);
         //其他索引的圖片都是跳到第二張圖
     }
  }
},
computed: {
  swiper() {
    return this.$refs.mySwiper.swiper
  },
  swiperOption(){
    let _this = this  // _this為VUE實(shí)例勇哗,要特別注意
    return {
       initialSlide :1,
       on: {
         //滑動事件
         //on事件里面的this指向swiper實(shí)例昼扛,要特別注意
         transitionEnd: function(){
                //isEnd為true,表示用戶向右滑動
                if(this.isEnd){
                   if(_this.curIndex < (_this.items.length-1)){
                        _this.curIndex = _this.curIndex + 1
                      }
                }
               //isBeginning為true欲诺,表示用戶向左滑動
                if(this.isBeginning){
                   if(_this.curIndex >= 1){
                        _this.curIndex  = _this.curIndex - 1
                   }
                } 
               //這里做的是特殊處理抄谐,
              // 因?yàn)楫?dāng)前圖片為最后一張時候,選中的圖片為第三張扰法,
              //swiperPicList數(shù)組中也是第三張蛹含,
              //最后一張滑動的方向只有向左,所以_this.curIndex - 1
             //做這個處理是最后一張向左滑動因?yàn)榉祷財?shù)組的原因塞颁,不能用isBeginning來判斷
               if(_this.curIndex == (_this.items.length-1)){
                     _this.curIndex = _this.curIndex - 1
                }
          },
       }
     }
   },
}

最終效果


image.png

初衷是想讓swiper不需要渲染所有的圖片浦箱,臨時做一個小數(shù)組,每次切換祠锣,小數(shù)組都是動態(tài)的獲取相鄰的三張照片酷窥,可能不是最優(yōu)的方法,創(chuàng)建數(shù)組也可以進(jìn)行再封裝锤岸。

以上只是傳達(dá)一個優(yōu)化思想

swiper參考文檔:https://www.swiper.com.cn/api/methods/109.html

- 第三部分:

問題:圖片列表竖幔,頁面上幾百上千張圖片,用戶訪問頁面是偷,要拉很長時間拳氢,還要考慮用戶在頁面來回滾動的情況
一募逞、圖片多,要拉很長時間

①馋评、懶加載放接,這個很簡單。
②留特、緩存纠脾,這個也很簡單。

二蜕青、考慮到用戶在頁面上下來回滾動

③苟蹈、節(jié)流防抖

節(jié)流:在頻繁觸發(fā)的情況下,按照一定的時間去執(zhí)行右核。

//聲明一個變量當(dāng)標(biāo)志位慧脱,記錄當(dāng)前代碼是否在執(zhí)行
const Throttling = (fn,intelval) => {
    let time = null;
        return function (){
            if(!time){
                time = setTimeout(() => {
                    fn.call(this,arguments)
                    time = null
                },intelval) 
            }
     }
}

防抖:在頻繁觸發(fā)的情況下,只有足夠的空閑時間贺喝,才執(zhí)行一次菱鸥。

//setTimeout做緩存池
const Throttling = (fn,delay) => {
    let time;
    return function (){
        if(time) clearTimeout(time)
        time = setTimeout(() => {
           fn.call(this,arguments)
        },delay) 
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市躏鱼,隨后出現(xiàn)的幾起案子氮采,更是在濱河造成了極大的恐慌,老刑警劉巖染苛,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鹊漠,死亡現(xiàn)場離奇詭異,居然都是意外死亡殖侵,警方通過查閱死者的電腦和手機(jī)贸呢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拢军,“玉大人,你說我怎么就攤上這事怔鳖≤园Γ” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵结执,是天一觀的道長度陆。 經(jīng)常有香客問我,道長献幔,這世上最難降的妖魔是什么懂傀? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮蜡感,結(jié)果婚禮上蹬蚁,老公的妹妹穿的比我還像新娘恃泪。我一直安慰自己,他們只是感情好犀斋,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布贝乎。 她就那樣靜靜地躺著,像睡著了一般叽粹。 火紅的嫁衣襯著肌膚如雪览效。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天虫几,我揣著相機(jī)與錄音锤灿,去河邊找鬼。 笑死辆脸,一個胖子當(dāng)著我的面吹牛衡招,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播每强,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼始腾,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了空执?” 一聲冷哼從身側(cè)響起浪箭,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辨绊,沒想到半個月后奶栖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡门坷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年宣鄙,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片默蚌。...
    茶點(diǎn)故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡冻晤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绸吸,到底是詐尸還是另有隱情鼻弧,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布锦茁,位于F島的核電站攘轩,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏码俩。R本人自食惡果不足惜度帮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望稿存。 院中可真熱鬧笨篷,春花似錦瞳秽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至安聘,卻和暖如春痰洒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背浴韭。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工丘喻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人念颈。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓泉粉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親榴芳。 傳聞我的和親對象是個殘疾皇子嗡靡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評論 2 354