jQuery按需加载轮播图(web前端性能优化)
引言
关于幻灯轮播图,想必大家都不陌生,尤其是基于 jQuery 的,插件、代码网上一搜一大堆,但是真正符合自己需求的几乎没有,所以我要打造一个符合自身需求,经得起广大网民考验的 jQuery 轮播图!
思路
为什么说网上其他一些轮播图不符合我的要求?我的需求又是什么呢?
现在网上可以找到的多数幻灯轮播图的 jQuery 插件的作法是,先把图片和链接的 HTML 写好,然后控制隐藏和显示来轮流展示当前的幻灯图片。但是对用户而言,我们始终只是看到当前的一张图片,那其他几张隐藏的图片为什么要事先加载进来呢?这不是费时费力吗?所以我的第一个需求是按需加载。
我们一般会把轮播图放在首页展示,但是首页的重点内容应该是最近更新的文章,至少我不认为图片展示功能需要被搜索引擎收录,所以我的第二个需求是符合 SEO。
实现
冲着以上两个需求,我做了一个 DEMO ,大家不妨看看这个 DEMO 的源代码,发现区别了吗?是的,在这个 DEMO 的 HTML 源代码中,你看不到任何的图片和相关信息,都由 JS 载入进来的,也就是说爬虫爬不到,而且是随着图片的切换,一张一张地载入当前的幻灯图片。
这里我就只分享一下我的 JS 写法,HTML 什么就请各位看源码吧,代码我就不一一细说了,注释也都写得很明白了。
$(function() { var WangeSlide = (function() { //配置 var config = { //轮播图尺寸 width : 960, height : 350, //是否自动切换 autoSwitch : true, //自动切换间隔时间(毫秒) interval : 6000, //轮播图图片路径 picPath : 'http://www.dowebok.com/demo/2014/93/img/', //轮播图图片信息:图片文件名 / 图片标题 / 图片指向链接 picInfo : [ ['fullimage1.jpg', '图片1提示','http://codepen.io/webstermobile/'], ['fullimage1.jpg', '图片2提示','http://codepen.io/webstermobile/'], ['fullimage1.jpg', '图片3提示','http://codepen.io/webstermobile/'] ] }; //获取图片信息 /** * @param index 图片所在的索引值 **/ var getImgInfo = function(index) { var imgSrc = config.picPath + config.picInfo[index][0], imgAlt = config.picInfo[index][3], imgUrl = config.picInfo[index][4], imgId = 'slide_' + (index+1).toString(), imgHtml = '<li id="' + imgId + '">' + ' <a href="' + imgUrl +'" rel="external nofollow" title="' + imgAlt + '" class="pic">' + ' <img src="' + imgSrc + '" alt="' + imgAlt + '" class="slide_thumb" />' + ' </a>' + '</li>', slideTextHtml = '<a href="' + imgUrl + '" rel="external nofollow" title="' + imgAlt + '">' + imgAlt+ '</a>'; return { imgAlt : imgAlt, imgUrl : imgUrl, imgHtml : imgHtml, slideTextHtml : slideTextHtml } }; //图片完全加载后缓慢加载显示 var fadeInImg = function(el, speed) { //console.log(el) el.find("img").load(function() { el.find("img").addClass("loaded") el.fadeIn(speed) }); }; //图片切换 /** * @param index 图片所在的索引值 * @param triggerCurEl 当前触发节点元素 **/ var imgSwitch = function(index, triggerCurEl) { var slideId = 'slide_' + (index+1).toString(), slideIdEl = document.getElementById(slideId); if (slideIdEl) { //如果已有对应的元素,则显示已有元素 var panelLi = $('#panel ul li'); panelLi.hide(); $(slideIdEl).fadeIn('slow'); } else { //如果还没有对应的元素,则注入元素 $(getImgInfo(index).imgHtml).appendTo($('#panel ul')); var panelLi = $('#panel ul li'); panelLi.hide(); //载入显示图片 fadeInImg($("#" +slideId), 'slow'); } //获取图片的 alt 作为显示信息 $('#slide_text').html(getImgInfo(index).slideTextHtml); //当前状态 cur $('#trigger ul li').removeClass('cur'); triggerCurEl.addClass('cur'); }; //轮播图 var slide = function() { //设置轮播图尺寸 $('#panel').css({ 'width' : config.width + 'px', 'height' : config.height + 'px' }); var result = getImgInfo(0).imgHtml //初使化轮播图,只加载第一张图片信息 $('#panel ul').html($(result)); //载入显示图片 fadeInImg($('#slide_1'), 500); //注入背景层 + 触发器容器 + 轮播图文字容器 var slideBg = '<div id="slide_bg"></div>', trigger = '<div id="trigger"></div>', slideText = '<div id="slide_text"></div>'; $('#panel').after(slideBg + trigger + slideText); //获取图片的 alt 作为显示信息 $('#slide_text').html(getImgInfo(0).slideTextHtml); //注入触发节点 var triggerUl = $('<ul></ul>'); triggerUl.appendTo($('#trigger')); for (var i=0, j=config.picInfo; i<j.length; i++) { $('<li>' + (i+1).toString() +'</li>').appendTo(triggerUl); } //当前状态 cur $('#trigger ul li').eq(0).addClass('cur'); //点击触发节点 $("#trigger ul li").click(function(){ var index = $("#trigger ul li").index($(this)) //console.log(index) imgSwitch(index,$(this)) }) //鼠标悬停时,停止切换 var goSwitch = true; $('#panel').hover( function() {goSwitch = false}, function() {goSwitch = true} ); //自动切换 if (config.autoSwitch) { setInterval(function() { if (goSwitch) { //判断当前cur所在的索引值 var index = parseInt($('.cur','#trigger').text()) - 1; if (index > (config.picInfo.length-2)) { index = -1; } imgSwitch((index+1), $('#trigger ul li:eq(' + (index+1) + ')')); } }, config.interval); } }; return { //初使化 init : function() { slide(); } } })(); WangeSlide.init(); })
按需加载的网络请求情况
从图上可以看到页面加载的时候自动切换或者用户点击切换之前只加载了一张slide图,大大节省了页面加载量。
优势
同样的效果,只是实现方法不同?会不会很蛋疼?这有什么优势呢?
举个例子来说,优化前,假设首页切换的幻灯图片有5张,平均每张图片20K,也就是说你的首页至少要加载100K的图片,而这100K的图片你能保证每个用户都会去看吗?如果用户不看,岂不是白白浪费了这100K的载入速度?
优化后,在首页初次载入的时候,仅需加载一张1K左右的,甚至是可有可无的 loading 图片,当用户点击下一张或者达到定时器的设置时才会去加载下一张图片,大大节省了载入的时间。1K?100K?你懂的。
另外,用 JS 载入所需的图片还有一个好处,就是在一些不支持 JS 的手机浏览器上,载入 100K 的图片对于无法切换的轮播图而言,是一个极大的累赘,而且也会大大降低用户体验。