TWEEN动画、JQUERY、ES6 — 4、 jQuery源码解读及插件封装

1、jQ的版本和下载

jQuery(jQ)的版本

1.x:兼容ie6~8浏览器,是目前pc端开发常用的类库

2.x/3.x:不支持ie6~8的兼容了,目前市场上应用的特别少(移动端开发一般我们都用zepto.js)

jquery-1.9.1.min.js

jquery-1.11.3.min.js

jquery.min.js

下载jQ

官网下载:jquery.com/

GitHub:github.com/jquery/jque… 下载jQ的源码进行学习和分析

百度搜索或或者在 code.jquery.com/jquery-1.11… (地址后面放入的是对应的jq的版本号)

基于NODE的npm包管理器也可以下载jq

npm view jquery > jquery.version.json
npm install jquery 下载最新版本jq
npm install jquery@1.11.3 下载制定版本jq
复制代码

如何学习jq

研究jq的源码:研究的过程更多是学习jq的编程精华,促进自己的原生js能力以及插件或者类库的封装能力

看jQ的API手册:jquery.cuishifeng.cn/

锋利的jq第二版:对于jq的基础知识和实战应用讲解的非常好

看一些jq的视频(不推荐,浪费时间)

2、jQ的核心原理

jQ的核心原理解读(分析源代码)

jQ是一个常用方法类库(常用的DOM库),提供了很多真实项目开发中需要使用的属性和方法(这些方法jQ已经帮我们完善了浏览器兼容处理以及一些细节的优化)。之前封装的utils跟jQ很类似

jquery本身是一个类,jQ是基于构造函数模式构建的类库

// 这些所有的判断操作是为了迎合node当中关于模块的管理来完成的,node中的内置模块,第三方模块以及模块管理用的就是
// module和module.exports来做的
(function( global, factory ) {
	if ( typeof module === "object" && typeof module.exports === "object" ) {
		// For CommonJS and CommonJS-like environments where a proper window is present,
		// execute the factory and get jQuery
		// For environments that do not inherently posses a window with a document
		// (such as Node.js), expose a jQuery-making factory as module.exports
		// This accentuates the need for the creation of a real window
		// e.g. var jQuery = require("jquery")(window);
		// See ticket #14549 for more info
		module.exports = global.document ?
			factory( global, true ) :
			function( w ) {
				if ( !w.document ) {
					throw new Error( "jQuery requires a window with a document" );
				}
				return factory( w );
			};
	} else {
		factory( global );
	}

// Pass this if window is not defined yet
// node中的全局变量global,而js中全局变量叫window,如果是window用window,如果不是winow用this(global)
}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {

//--------------------------------------------------------------------------------------------------------------

var jQuery = function( selector, context ) {
		return new jQuery.fn.init( selector, context );
};

jQuery.fn = jQuery.prototype = { // jQuery.fn就是jq的原型
    jquery: version,
    constructor: jQuery,//批量扩展类的原型上的方法需要改变constructor
    // ...给实例使用的方法(jq是一个类。原型上提供的属性和方法是供他实例使用的)
};

// new jQuery.fn.init( selector, context ):执行的就是jQuery.fn.init这个方法,创建这个方法这个类的一个实例
init = jQuery.fn.init = function( selector, context ) {
   
    	if ( typeof selector === "string" ) {
    	    ...
    	} else if ( selector.nodeType ) {
    	    ...
    	}else if ( jQuery.isFunction( selector ) ) {
    	    ...
    	}
    	
    	//makeArray源码中是创建一个类数组
    	return jQuery.makeArray( selector, this );//最终返回一个类数组
};

// jQuery.fn是jq的原型(jQuery.fn = jQuery.prototype);init.prototype = jQuery.fn:jQuery.fn.init()是一个方法,如果把
// init这个方法作为一个类的话,它的原型跟jq的原型一样,返回的结果不管是init的实例还是jq的实例,最终用的原型都是jq的原型。
// 只要用jq的原型,返回的就是jq类的一个实例,所以说jq本身就是一个类,通过jq方法返回的结果其实就是jq这个类的实例,不管new的是谁
// (这里 new jQuery.fn.init()),已经让init的原型等于jq的原型,也就是init的实例也指向jq的原型,所以返回的结果就是jq类的一个实例
init.prototype = jQuery.fn;

...

window.jQuery = window.$ = jQuery;//把jQuery当前这个类暴露在全局下,即可用jQuery也可用$

//结论:init.prototype = jQuery.fn这一步的意思就是,init的实例其实也是jq的实例,最终执行jQuery 这个方法返回
// return new jQuery.fn.init( selector, context )其实就是返回一个jq的一个实例,可以用jq原型上提供的方法,
// 最终init方法返回的结果是一个类数组,也是jq的一个实例。结合了单列思想和构造函数思想

// 当我们在js中执行
$()
jQuery()
// 都是在创建一个jq类的实例($===jQuery),这些实例都是一个类数组(我们把这个类数组称之为jq对象),
// jq的实例可以使用jq原型上提供的公有属性和方法
// 项目中我们把$()称之为jq的选择器

复制代码

什么叫jq的选择器:

1、执行jq的方法创建jq类的实例

2、因为执行这个方法可以传递一个selector参数进去,通过selector我们可以获取到需要操作的DOM元素集合(jq类数组集合) ,传递的第二个参数context它是当前获取元素的上下文(不传递默认是document,如果传递,我们传递一个js元素对象即可)

但是把它叫做jq选择器有点笼统,因为传递的selector支持三种格式:

  • 传递的是字符串,就是我们所谓的选择器,能够通过选择器获取到元素

  • 传递的是个元素对象,它的意思是把js原生对象转换为jq对象

  • 传递的是个函数,它代表等dom结构加载完成再执行对应的js代码(类似window.onload)

jQ的选择器

$===jQuery  //=>true
$()===jQuery() //=>false 不同实例
$() instanceof jQuery //=>true
var $example=$(); //=>我们用JQ选择器获取的值,一般都是用以$开头的变量名来存储(以后看见变量名是以$开头的,我们就知道是JQ获取的实例[JQ对象])
/*
 * $example
 *   [xxx:xxx  私有的属性]
 *   0:某一个元素对象
 *   ...
 *   length:类数组的长度
 *   context:document
 *   selector:''传递的选择器内容
 *   
 *   __protot__:jQuery.prototype
 *       [xxx:xxx 公有的属性和方法]
 *       add
 *       addClass
 *       ...  
 *       
 *      __proto__:Object.prototype  
 */
复制代码

第一个参数[selector]传递的是一个字符串,就是通过选择器获取需要的元素集合(获取的结果怎么着都是类数组集合:获取多个元素也就是索引多点,获取一个元素也就是只有索引0,一个都没获取到就是一个空的类数组集合[而不是null])

一般CSS或者CSS3中支持的选择器,JQ都支持

//=>基本选择器
$('#xxx')  
$('.xxx')  
$('xxx')  
$('*')  
$('.xxx,#xxx')

//=>后代选择器
$('.box a')
$('.box>a')
//$('.box~a')
//$('.box+a') 不常用

//=>伪类选择器
$('.box:contains(xxx)') 包含某某某内容的
$('a:first')
$('a:last')
$('a:eq(1)') 索引为1的
$('a:gt(1)') 索引大于1的
$('a:lt(10)') 索引小于10的
$('a:not()') 不包含什么的
$('a:not(:gt(5))') 获取所有的a,但是不包含索引大于5的(前六个)
...

//=>属性选择器
复制代码

3、jQ对象和原生js对象的相互转换

JQ对象:通过$()获取的JQ实例(类数组)

原生JS对象:通过ES中提供的属性或者方法获取的JS元素对象(nodeType===1)

把原生JS对象转换为JQ对象

var oBox=document.getElementById('box');//=>原生JS对象

//oBox.addClass();//=>报错:oBox不是JQ对象,不能使用JQ原型上的方法

var $box=$(oBox); //=>把原生JS对象转换为JQ对象
$box.addClass('bg');

复制代码

把JQ对象转换为原生JS对象

var $body=$('body');
//$body.className //=>undefined,因为className是JS原生内置的属性,JQ对象不能直接的用

//$body[索引]:在集合中获取指定索引的内容(获取的内容就是原生JS对象)
//$body.get(索引):等价于 $body[索引],获取指定索引位置的元素(原生JS对象)
//$body.eq(索引):获取指定索引位置的元素对象(获取的结果还是一个新的JQ对象)
复制代码

4、jQ中的document.ready应用

$(function(){
	//=>当页面中的DOM结构加载完成,就会执行回调函数中的JS代码
	//=>类似于window.onload:等到页面中的DOM结构以及资源文件都加载完成才会执行对应的JS代码
});

$(document).ready(function(){
	//=>这种写法和上面的写法一模一样
});
复制代码

和window.onload不太一样

1、$(function(){}) 可一在同一个页面中使用多次,多次都生效(所以在使用JQ完成代码的时候,我们一般都会把代码放在回调函数中:首先不仅是等到结构加载完在执行,而且还形成了一个闭包)

原理:利用了DOM二级事件绑定(可以执行多次),监听的是DOMContentLoaded事件(DOM结构加载完成就会触发执行)

2、window.onload本身就是资源都加载完成才会执行,使用的是DOM零级事件绑定,在同一个页面中只能使用一次

window.onload=function()...

window.onload=function()...

只能留最后一个,最后一次赋值替换了原有赋值
复制代码

5、jQ中的常用的方法(对照API文档过一遍)

JQ即是一个类也是一个对象

jQuery.prototype上设置了很多的属性和方法,这些是供JQ实例(DOM集合或者DOM元素)使用的属性和方法

addClass

css

removeClass

attr

...

jQuery也是一个普通的对象,在对象上也有一些自己的属性和方法(和实例没有任何的关系),这些都是工具类的方法

ajax

isFunction

unique

...

jQuery.prototype上的方法

$('#box').index():获取当前元素的索引(是在自己兄弟元素中的索引,它有几个哥哥,索引就是几)

$('body').data(key,value)
只传递key是获取
如果传递了value是设置
我们通过这个方法可以获取到在HTML结构上设置的data-xxx的自定义属性值
//<body data-index='12'></body>
//$('body').data('index') =>12

$('#box').attr():设置或者批量设置或者获取当前元素的自定义属性(内置属性也可以)  removeAttr
$('#box').prop():和attr一样也是操作元素属性的,但是prop一般都操作表单元素的内置或者自定义属性 removeProp

addClass:增加样式类
removeClass:移除样式类
toggleClass:当前样式类有就是移除,没有就是增加
hasClass:验证是否存在某个样式类名

$('#box').html([val]):不传val就是获取内容,传递val就是设置内容,等价于原生的innerHTML
$('input').val([val]):表单元素value值的操作(设置或者获取)

css:设置或者批量设置或者获取元素的样式(获取的结果没有去单位)

offset():获取距离BODY的偏移
position():获取距离父级参照物的偏移
scrollTop/scrollLeft([val]):获取或者设置当前元素卷去的高度或者宽度
height/width([val])
innerWidth/innerHeight():等价于clientWidth/clientHeight
outerWidth/outerHeight():等价于offsetWidth/offsetHeight

$('#box').on('click',function...):JQ中的事件绑定
...

$('#box').remove():把当前盒子在容器中移除
$('#box').clone(true):把当前盒子深度克隆一份

filter
children
find
...
复制代码

写在对象上的方法

var j=$.noConflict():如果当前项目中引入了两个类库,都是使用$操作的,为了防止$使用权的冲突,JQ做了一个处理,可以让我们转让$的使用权;此处返回的值j就是代表原始$的变量,以后可以使用j()执行(使用jQuery()执行也可以)

var j=$.noConflict(true):深度转让,把jQuery和$的使用权都转让了,此时只能使用j()执行了

$.ajax():帮助我们发送ajax请求

...
复制代码

animate:JQ中提供了元素运动的动画库


 stop:结束当前元素正在运行的动画,继续执行下一个新动画(一般我们实现动画,stop方法基本上必然执行)
 finish:和stop类似,finish需要让元素立即运动到上一个动画的目标位置,从目标位置执行下一个动画,而stop是从上一个动画停止的位置执行下一个动画
 
 animate([target],[duration],[effect],[callBack]):
 [target] 对象
 [duration] MS
 [effect]  linear、ease、ease-in、ease-out、ease-in-out
 [callBack] 回调函数,动画结束做的事情
  
 show(1000/'fast'/'slow')   
 hide  
 toggle
  
 fadeIn
 fadeOut
 fadeToggle
  
 slideUp
 slideDown
 slideToggle
复制代码

6、jQ中的常用的三个筛选方法

filter:同级过滤

children:子集过滤

find:后代过滤

var $links=$('a');
$links.filter('.bg'); //=>首先获取所有的A,在所有的A中把具备样式类为bg的获取到(二次筛选)

$('#box').children('a'); //=>首先获取#box所有的子元素,在所有子元素中筛选出标签名为a的元素集合 <=> $('#box>a')

$('#box').find('.bg'); //=>首先获取#box后代中所有的元素,在所有的元素中筛选出样式类名中具备bg的元素集合 <=> $('#box .bg')

//prev:获取上一个哥哥  $('#box').prev('a')
//prevAll:所有的哥哥
//next:下一个弟弟
//nextAll:所有的弟弟
//siblings:所有的兄弟
//parent:父亲元素
//parents:所有的祖先元素(一直到html为止)
复制代码

7、关于jQ中的EACH方法解读

JQ中的each有三种

1、写在原型上的each:遍历JQ对象中的每一项

2、写在对象上的each:工具方法,可以用来遍历数组、类数组、对象等

3、内置的each其实也是调用原型上的each处理的,只不过JQ在处理的时候会内部自己调用

//=>内置EACH
$('a').addClass('select'); //=>我们获取的A可能有很多个,执行一次addClass,相当于给每个获取的A都增加了一个叫做select的样式类(JQ中大部分方法在执行的时候,都会把获取的JQ集合中的每一项调用each进行遍历,把需要操作的任务对每一个遍历的元素进行操作)

$('a').css('width'); //=>获取的时候只返回第一个元素的样式(设置走内置EACH批量处理,获取只处理第一个)

//=>原型上的EACH
$('a').each(function(index,item){
	//=>传递参数的顺序和数组内置的forEach顺序相反:ary.forEach(function(item,index){...});
    //=>获取的A有多少个,回调函数被触发执行多少次:index当前遍历这一项的索引 item是当前遍历这一项的内容
    //=>this -> item (原生JS对象) 方法中的this是当前遍历的这一项
    //=>$(this) 也是当前遍历这一项,但是属于JQ对象
});

//=>JQ对象上提供的工具方法:each
$.each([数组/类数组], function(index,item) {
	//=>this:item
});
$.each([对象],function(key,value){
	//=>this:value
	//=>JQ也是采用for in循环用来遍历对象的,这样的话就存在可能把公有属性和方法遍历到的问题
	if([对象].hasOwnProperty(key)){
		
	}
});
复制代码

8、使用jQ完成选项卡操作

先实现一个tabBox的功能

tab.css

.tabBox {
    margin: 20px auto;
    width: 500px;
    font-size: 14px;
}

.tabBox .tab {
    position: relative;
    top: 1px;
}

.tabBox .tab li {
    float: left;
    margin-right: 15px;
    padding: 0 15px;
    height: 35px;
    line-height: 35px;
    border: 1px solid #999;
    background: #EEE;
    cursor: pointer;
}

.tabBox .tab li.select {
    background: #FFF;
    border-bottom-color: #FFF;
}

.tabBox .con {
    display: none;
    padding: 10px;
    height: 150px;
    border: 1px solid #999;
}

.tabBox .con li {
    line-height: 29px;
    border-bottom: 1px dashed #CCC;
}

.tabBox .con.select {
    display: block;
}
复制代码

case-tab.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <!--IMPORT CSS-->
    <link rel="stylesheet" href="css/reset.min.css">
    <link rel="stylesheet" href="css/tab.css">
</head>
<body>
<div class="tabBox" id="tabBox">
    <ul class="tab clearfix">
        <li>新闻</li>
        <li>电影</li>
        <li>动漫</li>
    </ul>
    <div class="con">
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
        </ul>
    </div>
    <div class="con">
        <ul>
            <li>6</li>
            <li>7</li>
            <li>8</li>
            <li>9</li>
            <li>10</li>
        </ul>
    </div>
    <div class="con">
        <ul>
            <li>11</li>
            <li>12</li>
            <li>13</li>
            <li>14</li>
            <li>15</li>
        </ul>
    </div>
</div>


<!--IMPORT JS-->
<script src="js/jquery-1.11.3.min.js"></script>
<script src="js/tab-backup.js"></script>
</body>
</html>
复制代码

tab-backup.js

// 使用单列模式先实现一个的功能
var tabRender = (function () {
    var $tabBox = $('#tabBox'),
        $tabList = $tabBox.find('.tab>li'),
        $conList = $tabBox.children('.con');

    var _default = {
        initIndex: 0,
        eventType: 'click'
    };

    function bindEvent() {
        $tabList.on(_default.eventType, function () {
            //=>this:current click li
            var $this = $(this),
                _index = $this.index();
            $this.addClass('select')
                .siblings().removeClass('select');
            $conList.eq(_index).addClass('select')
                .siblings().removeClass('select');
        });
    }

    function initDefault() {
        $tabList.removeClass('select');
        $conList.removeClass('select');
        $tabList.eq(_default.initIndex).addClass('select');
        $conList.eq(_default.initIndex).addClass('select');
    }

    return {
        init: function (options) {
            //=>init parameters
            if (typeof options !== 'undefined') {
                $.each(options, function (key, value) {
                    if (options.hasOwnProperty(key)) {
                        _default[key] = value;
                    }
                });
            }

            initDefault();
            bindEvent();
        }
    }
})();
tabRender.init({
    initIndex: 1,
    eventType: 'mouseover'
});

复制代码

9、使用jQ实现选项卡插件的封装

jQ中扩展插件有两种方法

$.extend():把方法扩展到JQ对象上,这个操作一般是用来完善类库的

$.fn.extend():把方法扩展到JQ的原型上,供JQ的实例(DOM集合)使用,这个操作一般是用来写JQ插件的

//=>扩展工具方法,用来完善类库
$.extend({
	aa:function(){}
});
$.aa();

//=>扩展到原型上供实例调用的
$.fn.extend({
	bb:function(){
		//=>this:操作当前这个方法的JQ实例(JQ对像),此处不需要再$(this)转换为JQ对像
	}
});
$('xxx').bb();
复制代码

html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <!--IMPORT CSS-->
    <link rel="stylesheet" href="css/reset.min.css">
    <link rel="stylesheet" href="css/tab.css">
</head>
<body>
<div class="tabBox">
    <ul class="tab clearfix">
        <li>新闻</li>
        <li>电影</li>
        <li>动漫</li>
    </ul>
    <div class="con">
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
        </ul>
    </div>
    <div class="con">
        <ul>
            <li>6</li>
            <li>7</li>
            <li>8</li>
            <li>9</li>
            <li>10</li>
        </ul>
    </div>
    <div class="con">
        <ul>
            <li>11</li>
            <li>12</li>
            <li>13</li>
            <li>14</li>
            <li>15</li>
        </ul>
    </div>
</div>

<div class="tabBox">
    <ul class="tab clearfix">
        <li>新闻</li>
        <li>电影</li>
        <li>动漫</li>
    </ul>
    <div class="con">
        1
    </div>
    <div class="con">
        2
    </div>
    <div class="con">
        3
    </div>
</div>

<div class="tabBox">
    <ul class="tab clearfix">
        <li>新闻</li>
        <li>电影</li>
        <li>动漫</li>
        <li>科技</li>
    </ul>
    <div class="con">
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
        </ul>
    </div>
    <div class="con">
        <ul>
            <li>6</li>
            <li>7</li>
            <li>8</li>
            <li>9</li>
            <li>10</li>
        </ul>
    </div>
    <div class="con">
        <ul>
            <li>11</li>
            <li>12</li>
            <li>13</li>
            <li>14</li>
            <li>15</li>
        </ul>
    </div>
    <div class="con">
        <ul>
            <li>16</li>
            <li>17</li>
            <li>18</li>
            <li>19</li>
            <li>20</li>
        </ul>
    </div>
</div>

<!--IMPORT JS-->
<script src="js/jquery-1.11.3.min.js"></script>
<script src="js/tab.js"></script>
<!-- <script src="js/pluginTab.min.js"></script> -->
<script>
    $('.tabBox').each(function (index) {
        if (index === 0) {
            $(this).pluginTab();
        }

        if (index === 1) {
            $(this).pluginTab({
                initIndex: 1
            });
        }

        if (index === 2) {
            $(this).pluginTab({
                initIndex: 2,
                eventType: 'mouseover'
            });
        }
    });
</script>
</body>
</html>
复制代码

tab.js

// 使用构造函数模式封装插件  插件不适合使用单列模式
~function ($) {
    function pluginTab(options) {
        //=>THIS:当前你想让哪个选项卡实现切换,THIS就是当前选项卡的容器
        var $tabBox = this,
            $tabList = $tabBox.find('.tab>li'),
            $conList = $tabBox.children('.con');

        //=>init parameters
        var _default = {
            initIndex: 0,
            eventType: 'click'
        };
        options && $.each(options, function (key, value) {
            if (options.hasOwnProperty(key)) {
                _default[key] = value;
            }
        });

        //=>show default
        change(_default.initIndex);

        //=>bind event
        $tabList.on(_default.eventType, function () {
            var $this = $(this),
                index = $this.index();
            change(index);
        });

        function change(index) {
            $tabList.eq(index).addClass('select')
                .siblings().removeClass('select');
            $conList.eq(index).addClass('select')
                .siblings().removeClass('select');
        }
    }

    $.fn.extend({ 
        pluginTab: pluginTab
    });
}(jQuery);
// 传递jQuery $接收的好处:必须保证有jQuery之后$才能用 
// 为了防止多库共存,不管有没有把jQuery库的$使用权转让,$使用权被转让 jQuery一般不会被转让 这里面私有变量$肯定是jQuery 

// 执行
// $('xxx').pluginTab();

复制代码

10~12、使用jQ封装轮播图(实现数据绑定和延迟加载)

case-banner.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <!--IMPORT CSS-->
    <link rel="stylesheet" href="css/reset.min.css">
    <link rel="stylesheet" href="css/banner.min.css">
</head>
<body>
<div class="container">
    <ul class="wrapper">
        <!--<li class="slide">
            <img src="" data-img="img/banner1.jpg" alt="">
        </li>-->
    </ul>
    <ul class="focusBox clearfix">
        <!--<li class="select"></li>
        <li></li>
        <li></li>
        <li class="last"></li>-->
    </ul>
    <a href="javascript:;" class="arrow arrowLeft"></a>
    <a href="javascript:;" class="arrow arrowRight"></a>
</div>

<div class="container">
    <ul class="wrapper">
        <!--<li class="slide">
            <img src="" data-img="img/banner1.jpg" alt="">
        </li>-->
    </ul>
    <ul class="focusBox clearfix"></ul>
</div>

<!--IMPORT JS-->
<script src="js/jquery-1.11.3.min.js"></script>
<script src="js/banner-backup.js"></script>
</body>
</html>
复制代码

banner-backup.js

// 自执行函数实现一个banner功能
~function (options) {
    var $container = $('#container'),
        $wrapper = $container.children('.wrapper'),
        $focusBox = $container.children('.focusBox'),
        $arrowLeft = $container.children('.arrowLeft'),
        $arrowRight = $container.children('.arrowRight');
    var $slideList = null,
        $imgList = null,
        $focusList = null,
        bannerData = null;

    //=>INIT PARAMETERS
    var _default = {
        initIndex: 0,
        autoInterval: 2000,
        showFocus: true,
        needFocus: true,
        eventFocus: 'mouseenter',
        showArrow: true,
        eventArrow: 'click',
        needAuto: true
    };
    options && $.each(options, function (key, value) {
        if (options.hasOwnProperty(key)) {
            _default[key] = value;
        }
    });
    var initIndex = _default.initIndex,
        autoInterval = _default.autoInterval,
        showFocus = _default.showFocus,
        needFocus = _default.needFocus,
        eventFocus = _default.eventFocus,
        showArrow = _default.showArrow,
        eventArrow = _default.eventArrow,
        needAuto = _default.needAuto;

    //=>GET DATA & BIND DATA
    ~function () {
        $.ajax({
            url: 'json/banner.json',
            method: 'get',
            dataType: 'json',
            async: false,
            success: function (result) {
                bannerData = result;
            }
        });

        var str = ``,
            strFocus = ``;
        $.each(bannerData, function (index, item) {
            str += `<li class="slide">
                <img src="" data-img="${item.img}" alt="">
            </li>`;

            if (showFocus) {
                strFocus += `<li class="${index === bannerData.length - 1 ? 'last' : ''}"></li>`;
            }
        });
        $wrapper.html(str);
        showFocus ? $focusBox.html(strFocus) : null;

        //->GET ELEMENT
        $slideList = $wrapper.children();
        $imgList = $wrapper.find('img');
        showFocus ? $focusList = $focusBox.children() : null;
    }();

    //=>INIT SHOW
    ~function () {
        $slideList.css({
            opacity: 0,
            zIndex: 0
        }).eq(initIndex).css({
            opacity: 1,
            zIndex: 1
        });

        if (showFocus) {
            $focusList.removeClass('select')
                .eq(initIndex).addClass('select');
        }
    }();

    //=>LAZY IMG
    $(window).on('load', function () {
        $imgList.each(function (index, item) {
            var tempImg = new Image;
            tempImg.onload = function () {
                item.src = this.src;
                item.style.display = 'block';
                tempImg = null;
            };
            tempImg.src = $(item).data('img');//<=>item.getAttribute('data-img')
        });
    });

    //=>CHANGE BANNER
    var autoTimer = null,
        count = bannerData.length;

    needAuto ? autoTimer = setInterval(autoMove, autoInterval) : null;
    function autoMove() {
        initIndex++;
        initIndex === count ? initIndex = 0 : null;
        change();
    }

    //=>OTHER CHANGE
    $container.on('mouseenter', function () {
        needAuto ? clearInterval(autoTimer) : null;

        if (showArrow) {
            $arrowLeft.css('display', 'block');
            $arrowRight.css('display', 'block');
        }
    }).on('mouseleave', function () {
        needAuto ? autoTimer = setInterval(autoMove, autoInterval) : null;

        if (showArrow) {
            $arrowLeft.css('display', 'none');
            $arrowRight.css('display', 'none');
        }
    });

    if (showArrow) {
        $arrowRight.on(eventArrow, autoMove);
        $arrowLeft.on(eventArrow, function () {
            initIndex--;
            initIndex === -1 ? initIndex = count - 1 : null;
            change();
        });
    }

    if (showFocus && needFocus) {
        $focusList.on(eventFocus, function () {
            initIndex = $(this).index();
            change();
        });
    }

    //=>CHANGE
    function change() {
        var $curSlide = $slideList.eq(initIndex);
        $curSlide.css('zIndex', 1)
            .siblings().css('zIndex', 0);
        $curSlide.stop().animate({opacity: 1}, 200, function () {
            $curSlide.siblings().css('opacity', 0);
        });

        //->focus
        if (showFocus) {
            $focusList.eq(initIndex).addClass('select')
                .siblings().removeClass('select');
        }
    }
}();
复制代码

13、使用jQ封装轮播图(插件封装)

case-banner.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <!--IMPORT CSS-->
    <link rel="stylesheet" href="css/reset.min.css">
    <link rel="stylesheet" href="css/banner.min.css">
</head>
<body>
<div class="container">
    <ul class="wrapper">
        <!--<li class="slide">
            <img src="" data-img="img/banner1.jpg" alt="">
        </li>-->
    </ul>
    <ul class="focusBox clearfix">
        <!--<li class="select"></li>
        <li></li>
        <li></li>
        <li class="last"></li>-->
    </ul>
    <a href="javascript:;" class="arrow arrowLeft"></a>
    <a href="javascript:;" class="arrow arrowRight"></a>
</div>

<div class="container">
    <ul class="wrapper">
        <!--<li class="slide">
            <img src="" data-img="img/banner1.jpg" alt="">
        </li>-->
    </ul>
    <ul class="focusBox clearfix"></ul>
</div>

<!--IMPORT JS-->
<script src="js/jquery-1.11.3.min.js"></script>
<!-- <script src="js/banner-backup.js"></script> -->
<script src="js/jquery-banner.min.js"></script>
<script>
    $('.container').each(function (index, item) {
        if (index === 0) {
            $(item).pluginBanner({
                url: 'json/banner.json',
                initIndex: 3,
                eventFocus: 'click'
            });
        }

        if (index === 1) {
            $(item).pluginBanner({
                url: 'json/banner2.json',
                autoInterval: 3000,
                needFocus: false,
                showArrow: false,
                needArrow: false
            });
        }
    });
</script>
</body>
</html>
复制代码

banner.js

// 使用构造函数插件封装
~function ($) {
    function pluginBanner(options) {
        var $container = this,
            $wrapper = $container.children('.wrapper'),
            $focusBox = $container.children('.focusBox'),
            $arrowLeft = $container.children('.arrowLeft'),
            $arrowRight = $container.children('.arrowRight');
        var $slideList = null,
            $imgList = null,
            $focusList = null,
            bannerData = null;

        //=>INIT PARAMETERS
        var _default = {
            initIndex: 0,
            autoInterval: 2000,
            showFocus: true,
            needFocus: true,
            eventFocus: 'mouseenter',
            showArrow: true,
            eventArrow: 'click',
            needAuto: true,
            url: null
        };
        options && $.each(options, function (key, value) {
            if (options.hasOwnProperty(key)) {
                _default[key] = value;
            }
        });
        var initIndex = _default.initIndex,
            autoInterval = _default.autoInterval,
            showFocus = _default.showFocus,
            needFocus = _default.needFocus,
            eventFocus = _default.eventFocus,
            showArrow = _default.showArrow,
            eventArrow = _default.eventArrow,
            needAuto = _default.needAuto;

        //=>GET DATA & BIND DATA
        ~function () {
            $.ajax({
                url: _default.url,
                method: 'get',
                dataType: 'json',
                async: false,
                success: function (result) {
                    bannerData = result;
                }
            });

            var str = ``,
                strFocus = ``;
            $.each(bannerData, function (index, item) {
                str += `<li class="slide">
                <img src="" data-img="${item.img}" alt="">
            </li>`;

                if (showFocus) {
                    strFocus += `<li class="${index === bannerData.length - 1 ? 'last' : ''}"></li>`;
                }
            });
            $wrapper.html(str);
            showFocus ? $focusBox.html(strFocus) : null;

            //->GET ELEMENT
            $slideList = $wrapper.children();
            $imgList = $wrapper.find('img');
            showFocus ? $focusList = $focusBox.children() : null;
        }();

        //=>INIT SHOW
        ~function () {
            $slideList.css({
                opacity: 0,
                zIndex: 0
            }).eq(initIndex).css({
                opacity: 1,
                zIndex: 1
            });

            if (showFocus) {
                $focusList.removeClass('select')
                    .eq(initIndex).addClass('select');
            }
        }();

        //=>LAZY IMG
        $(window).on('load', function () {
            $imgList.each(function (index, item) {
                var tempImg = new Image;
                tempImg.onload = function () {
                    item.src = this.src;
                    item.style.display = 'block';
                    tempImg = null;
                };
                tempImg.src = $(item).data('img');//<=>item.getAttribute('data-img')
            });
        });

        //=>CHANGE BANNER
        var autoTimer = null,
            count = bannerData.length;

        needAuto ? autoTimer = setInterval(autoMove, autoInterval) : null;
        function autoMove() {
            initIndex++;
            initIndex === count ? initIndex = 0 : null;
            change();
        }

        //=>OTHER CHANGE
        $container.on('mouseenter', function () {
            needAuto ? clearInterval(autoTimer) : null;

            if (showArrow) {
                $arrowLeft.css('display', 'block');
                $arrowRight.css('display', 'block');
            }
        }).on('mouseleave', function () {
            needAuto ? autoTimer = setInterval(autoMove, autoInterval) : null;

            if (showArrow) {
                $arrowLeft.css('display', 'none');
                $arrowRight.css('display', 'none');
            }
        });

        if (showArrow) {
            $arrowRight.on(eventArrow, autoMove);
            $arrowLeft.on(eventArrow, function () {
                initIndex--;
                initIndex === -1 ? initIndex = count - 1 : null;
                change();
            });
        }

        if (showFocus && needFocus) {
            $focusList.on(eventFocus, function () {
                initIndex = $(this).index();
                change();
            });
        }

        //=>CHANGE
        function change() {
            var $curSlide = $slideList.eq(initIndex);
            $curSlide.css('zIndex', 1)
                .siblings().css('zIndex', 0);
            $curSlide.stop().animate({opacity: 1}, 200, function () {
                $curSlide.siblings().css('opacity', 0);
            });

            //->focus
            if (showFocus) {
                $focusList.eq(initIndex).addClass('select')
                    .siblings().removeClass('select');
            }
        }
    }

    $.fn.extend({
        pluginBanner: pluginBanner
    });
}(jQuery);
复制代码

将banner.js压缩成jquery-banner.min.js

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值