22

7. jQuery 里的事件机制

javascriptHTML之间的交互是通过用户和浏览器操作页面时引发的事件来处理的。jQuery不仅提供了更加优雅的事件处理语法,而且极大地增强了事件处理能力。

7.1 加载 DOM

前面章节我们已经对比了window.onload()$(document).ready()两种方法的区别。两种都是入口函数,只不过前者是js中的而后者是jQ中的。并且领着之间还是有区别的:

1、执行时机:

window.onload()方法是等到页面中所有元素加载完毕之后,才执行,即javascript此时才可以访问网页中的任何元素。而jQuery使用$(document).ready()方法,可以在DOM载入就绪时就对其进行操纵并调用执行它所绑定的函数。也就是说在jQ中,不需要等待所有图片加载完再执行。

但是就会有个问题,当获取图片宽高的时候,可能获取不到。不过jQ中单独提出了一个页面加载的方法——load()方法,如果这个处理函数绑定给window对象则会在所有内容加载完毕之后触发。

$(window).load(function(){
   // 执行代码 
});

上面的代码,等同于js中的:

window.onload = function(){
    // 执行代码
}

2、多次使用:

javascript中入口函数只能写一次,如果写多个,下面会将上面的覆盖掉:

window.onload = function(){
    alert(123);
}

window.onload = function(){
    alert(456);             // 页面只会弹出 456
} 

jQuery中,入口函数可以写多次,不会出现覆盖的情况:

$(document).ready(function(){
   alert(123);          // 123               
});

$(document).ready(function(){
   alert(456);          // 456              
});

3、简写方式:
javascript中没有简写方式,但是在jQ中有简写方式:

// 1-原始版写法
$(document).ready(function(){
   // 执行代码 
});

// 2-简化写法,document可以省略
$().ready(function(){
   // 执行代码 
});

// 3-简化写法
$(function(){
    // 执行代码
});

7.2 事件绑定

1、什么是事件绑定

在文档装载完成之后,如果打算为元素绑定事件来完成某些操作,则可以使用bind()方法,bind()方法的调用格式为:
bind(type [, data] ,fn);

bind()方法有三个参数:

  • type:事件类型,类型包括:blur,focus,load,resize,scroll,unload,click,dbclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error等。
  • [,data]:可选参数,作为event.data属性值传递给事件对象的额外数据对象。
  • fn:用来绑定的处理函数。

示例代码: [ 38-jq事件机制-事件绑定.html ]

<!-- html 部分 -->
<h2>什么是相对论?</h2>
<div class="hide">
    <p>相对论是关于时空和引力的基本理论,主要由阿尔伯特·爱因斯坦创立,依据研究的对象不同分为狭义相对论和广义相对论。相对论的基本假设是相对性原理,即物理定律与参照系的选择无关。</p>
    <p>狭义相对论和广义相对的区别是,前者讨论的是匀速直线运动的参照系(惯性参照系)之间的物理定律,后者则推广到具有加速度的参照系中(非惯性系),并在等效原理的假设下,广泛应用于引力场中。相对论极大地改变了人类对宇宙和自然的“常识性”观念,提出了“同时的相对性”、“四维时空”、“弯曲时空”等全新的概念。它发展了牛顿力学,推动物理学发展到一个新的高度。</p>
    <p>狭义相对性原理是相对论的两个基本假定,在目前实验的观测下,物体的运动与相对论是吻合很好的,所以目前普遍认为相对论是正确的理论。</p>
</div>

<!-- js 部分 -->
<script>
    $(function() {
        // 绑定点击事件
        $('h2').bind('click', function() {
            // 选择器$(this).next() 多次出现,可以用一个变量接收 储存起来
            var $content = $(this).next();
            // is 方法 可以对元素的状态进行判断
            if ($content.is(":visible")) {
                $content.hide();
            } else {
                $content.show();
            }
        });
    });
</script>

效果图:

image

注意:

  • is()方法,可以用来判断一个元素是否包含某一属性。
  • 当一个选择器多次出现的时候,可以用一个变量将它缓存起来。

2、简写绑定事件

jQuery提供了一套简写的方法,简写的方法和bind()的使用方法类似,实现效果也相同,但是可以减少代码量:
$(function(){
    $('h2').click(function(){
       // 执行代码 
    });
});

7.3 合成事件

jQuery 有两个合成事件:hover()方法和toggle()方法(这里的toggle跟另一个方法toggle不是一个方法,这里的toggle方法因为重名的原因,已经在jQ1.8版本以后弃用了)。

1、hover()方法:

hover(enter,leaver); // enter 和 leaver 是两个函数

hover()方法用于模拟光标悬停事件。当光标移动到元素上的时候会触发第一个函数(enter),当光标离开元素的时候会触发第二个函数(leaver)。

示例代码: [ 39-jq事件机制-合成事件hover.html ]

$(function() {
    // hover 方法
    $('h2').hover(enter, leaver);
    var $content = $('h2').next();

    // 鼠标进入的时候触发的函数
    function enter() {
        $content.show();
    }

    // 鼠标离开时触发的函数
    function leaver() {
        $content.hide();
    }
});

2、toggle()方法:此方法自1.8版本以后,已弃用

toggle(fn1,fn2,...fnN);

toggle()方法,模拟的是鼠标单击事件,当点击第一次的时候,触发对应的第一个函数(fn1),当点击第二次的时候,触发对应的第二个函数(fn2),一直到最后一个函数的时候,再点击就会循环到第一个函数,就这样一直循环切换。

另外一个 toggle() 方法,是切换元素的可见状态,如果元素是可见的,事件触发之后,就会切换成不可见。

$('h2').click(function(){
    $(this).next().toggle(); // 如果元素一开始是隐藏的,点击之后就会切换成显示。
});

7.4 事件冒泡

在前面特效篇里面,我们已经介绍了什么是事件冒泡,这里不再累赘,简单来说,就是一个元素包含另一个元素,两个元素同时绑定了点击事件,当我点击里面元素的时候,会同时触发两个事件函数,这就是事件冒泡。

具体产生的原理,和解决办法请点击这个链接,这里会有处理兼容性的详细步骤。

示例代码: [ 40-jq事件机制-事件冒泡.html ]

<!-- html 部分 -->
<div class="box">
    <p>提示信息</p>
    <div class="box1">
        <p>提示信息</p>
        <div class="box2">
            <p>提示信息</p>
        </div>
    </div>
</div>

<!-- js 部分 -->
<script>
    $(function() {
        $('.box').click(function() {
            $(this).children('p').text(".box被触发了");
        });
        $('.box1').click(function() {
            $(this).children('p').text(".box1被触发了");
        });
        $('.box2').click(function() {
            $(this).children('p').text(".box2被触发了");
        });
    });
</script>

效果图:

image

我们可以看到,明明点击的是最里面的盒子,但是三个点击事件都同时触发了。

1、事件对象:

由于在IE-DOM和标准DOM实现事件对象的方法各不相同,所以需要处理兼容性。在jQuery中,已经将我们封装好了。 直接在触发事件函数里面传一个参数:
$('element').bind('click',function(event){
    // 执行代码
});

2、阻止事件冒泡:

阻止事件的方法存也在兼容性,同样的jQ中已经封装好,直接使用stopPropagation()方法来阻止事件冒泡。

示例代码: [ 41-jq事件机制-阻止事件冒泡.html ]

$(function() {
    $('.box').click(function(e) {                   // 事件对象
        $(this).children('p').text(".box被触发了");
        e.stopPropagation();                        // 阻止事件冒泡
    });
    $('.box1').click(function(e) {
        $(this).children('p').text(".box1被触发了");
        e.stopPropagation();

    });
    $('.box2').click(function(e) {
        $(this).children('p').text(".box2被触发了");
        e.stopPropagation();
    });
});

效果图:

image

3、阻止默认行为:

网页中有很多元素都有默认行为,例如,单击超链接后会跳转、单击提交按钮后表单会提交,有时候我们需要阻止元素的默认行为。

jQ中提供了一个方法来阻止元素的默认行为:preventDefault

不加阻止默认行为时的效果:

image

示例代码: [ 42-jq事件机制-阻止默认行为.html ]

<!-- html 部分 -->
<form action="test.html">
    <label for="username">用户名</label><input type="text" id="username" placeholder="请输入用户名">
    <br>
    <input type="submit" value="提交" id="sub">
</form>
<div id="msg"></div>

<!-- js 部分 -->
<script>
    $(function() {
        $('#sub').click(function(e) {           // 事件对象
            var $username = $('#username').val();
            if ($username == "") {
                $('#msg').html('<p>文本框的值不能为空</p>');
                e.preventDefault();         // 阻止默认行为
            }
        });
    });
</script>

效果图:

image

4、return false:

如果想要同时对事件停止冒泡和阻止默认行为,可以有一种默认的简写方式:return false

5、事件捕获:

jQ中不支持事件捕获,如果想要事件捕获的话,请参考原生的js

7.5 事件对象的属性

1、event.type:

该方法可以获取到事件的类型。
$("a").click(function(event){
    console.log(event.type);    // 打印a标签点击之后的事件类型  打印 ==> click
    return false;           // 阻止a标签默认跳转事件
});

2、event.stopPropagation()方法:

上面已经提过了,该方法是阻止事件冒泡。

3、event.preventDefault()方法:

上面已经提过了,该方法是阻止事件默认行为。

4、event.target:

该方法的作用是获取到触发事件的元素。
$("a").click(function(event){
    console.log(event.target);    // 打印 ==> a
    return false;                 // 阻止a标签默认跳转事件
});

5、event.pageX 和 event.pageY:

该方法的作用,是分别获取到光标相对于页面的x坐标和y坐标,如果页面上有滚动条的话,还要加上滚动条的宽度和高度。

6、event.which

该方法的作用是在鼠标单击事件中获取到鼠标的左、中、右键;在键盘事件中获取键盘的按键。

比如获取鼠标的按键:

$("a").mousedown(function(event){
    console.log(event.which);     // 鼠标左键==> 1 鼠标中键==> 2 鼠标右键==> 3 
    return false;                 // 阻止a标签默认跳转事件
});

比如获取键盘的按键:

$("input[text]").keyup(function(event){
    console.log(event.which);     // 对应按下的键盘码
});

7、event.metaKey:

该方法是针对不同浏览器,获取到<ctrl>按键。

7.6 移除事件

当我们想要移除一个事件的时候,可以使用unbind()方法。
unbind([type].[data]);

第一个参数是事件类型,第二个参数是将要移除的函数:

  • 如果没有参数,直接删除所有的绑定的事件;
  • 如果提供了事件类型作为参数,那只删除该类型的绑定事件;
  • 如果把在绑定时传递的处理函数作为第二个参数,则只有这个特定的事件处理函数会被删除。

示例代码: [ 43-jq事件机制-移除事件.html ]

<!-- html 部分 -->
<button id="btn1">点击弹出alert</button>
<br>
<button id="btn2">点击移除上一个btn点击事件</button>

<!-- js 部分 -->
<script>
    $(function() {
        // 点击第一个按钮 弹出信息
        $('#btn1').click(function() {
            alert('我是btn1');
        });
        // 点击第二个按钮移除第一个按钮的点击事件
        $('#btn2').click(function() {
            $('#btn1').unbind('click');
        });
    });
</script>

效果图:

image

7.7 模拟操作

什么是模拟操作呢?我们可以看到前面的单击事件,都需要手动去触发,模拟操作就是可以自动触发click,而不需要用户主动点击。
<!-- html 部分 -->
<button id="btn">点击弹出信息</button>

<!-- js 部分 -->
<script>
    $(function() {
        $('#btn').click(function() {
            alert("呵呵");
        });
        // $('#btn').click();
        $('#btn').trigger('click');
    });
</script>

一进入页面就会自动弹出“呵呵”,其中 $('#btn').click();,也可以达到同样的效果。

trigger()方法触发事件后,会执行浏览器默认操作:

$('input').trigger('focus');

上面的代码不仅会触发元素绑定的focus事件,也会使input元素本身得到焦点(这就是浏览器的默认操作)。

triggerHandler()方法:

如果你只想触发绑定的focus事件,而不想执行浏览器默认操作,可以使用triggerHandler()方法。
$('input').triggerHandler('focus');

7.8 事件委托

事件委托,首先按字面的意思就能看出来,是将事件交由别人来执行,再联想到事件冒泡,是不是想到了?对,就是将子元素的事件通过冒泡的形式交由父元素来执行。

举个例子:

假如想要给多个li都注册点击事件,只需要给li循环遍历,再添加点击事件,这种方法固然简单,但是假如有100个、1000li的时候,这里的DOM操无形之中就繁琐了。并且当我们动态添加li元素的时候,这些li是没有点击事件的。但是这些只要讲点击事件交给父元素来执行,就能实现了。

1、on + 注册事件:

除了bind方法绑定事件之外,在jQuery1.7版本之后,新添了一种方法:on()方法用来绑定事件,off()方法用来解除绑定事件。on()方法既可以注册事件,还可以注册委托事件。
$(element).on(type,[selector],fn);

参数详解:

  • type:字符串,事件类型,如:clickmouseover...;
  • selector:可选,字符串,用于过滤出被选中的元素中能触发事件的后代元素。如果选择器是 null 或者忽略了该选择器,那么被选中的元素总是能触发事件;
  • fn:事件被触发执行的函数。

示例代码:

<!-- html 部分 -->
<div>
  <p>111111</p>
  <p>111111</p>
  <p>111111</p>
  <p>111111</p>
  <i>123456</i>
</div>

<!-- js 部分 -->
<script>
$(function () {
    // 这个是p自己注册的事件(简单事件)
    $("p").on("click", function() {
        alert("p的点击事件");
    });
    
    //给div自己执行的
    $("div").on("click", function() {
        alert("div的点击事件");
    });

    //给div里面的p执行 委托事件
    $("div").on("click", "p", function() {
        alert("div里面的p的点击事件");
    });
});
</script>

效果图:

image

第二个参数其实就相当于一个过滤器的作用,给div里面的p注册委托事件。在执行顺序上,会先执行元素自己的事件,再去执行绑定的事件,最后执行父元素的事件。

当第二个参数传进去的时候,就想当于给过滤的元素注册委托事件

2、delegate 注册委托事件:

delegate只能注册委托事件。
$(fatheElement).delegate(selector,type,fn);

参数详解:

  • fatheElement:父元素;
  • selector:可选,字符串,用于过滤出被选中的元素中能触发事件的后代元素。如果选择器是 null 或者忽略了该选择器,那么被选中的元素总是能触发事件;
  • type:事件类型;
  • fn:事件被触发执行的函数。

7.9 其他用法

1、绑定多个事件类型:

$('div').bind('mouseover mouseout',function(){
   $(this).toggleClass("over");  // 当鼠标进入的时候,该元素的class属性切换为over 鼠标离开时class切换为先前的值
});

2、添加事件的命名空间:

$('div').bind('click.plugin',function(){
   alert(123); 
});

$('div').bind('mouseover.plugin',function(){
   alert(456); 
});

$('div').bind('dbclick',function(){
   alert(666); 
});

$('button').click(function(){
    $('div').unbind('.plugin'); 
});

其中.plugin就是命名空间,当点击button按钮的时候,就删除了事件的命名空间.plugin,此时对应的事件也会被移除。

相同的事件,不同的命名空间:

$('div').bind('click.plugin',function(){
   alert(456); 
});

$('div').bind('click',function(){
   alert(666); 
});

$('button').click(function(){
    $('div').trigger('click!');  // 注意后面的感叹号
});

当点击div的时候,会同时触发click.pluginclick事件,如果点击button只会触发click事件,而不会触发click.plugin事件。trigger('click!'),后面感叹号表示的是匹配所有不在命名空间中的click方法。

8. jQuery 动画

相对于原生jsjQuery中的动画更加的方便,更加的强大。

8.1 show()方法 和 hide()方法

当一个元素调用show()方法的时候,会将该元素的display设置为block,当调用hide()方法的时候,会将该元素的display设置为none
$('h2').bind('mouseover',function(){
    $(this).next().show();  // 鼠标进入的时候 h2 下一个兄弟元素显示
}).bind('mouseout',function(){
    $(this).next().hide();  // 鼠标离开的时候 h2 下一个兄弟元素隐藏
})

此时还没有动画的效果,下面给他们加上动画效果

下面的代码表示的是,元素在600ms内显示出来:

$('element').show(600);

下面的代码表示的是,元素在300ms内隐藏起来:

$('element').hide(300);

示例代码: [ 45-jq动画-show&hide.html ]

<!-- 样式部分 -->
<style>
    * {
        margin: 0;
        padding: 0;
    }
    h4 {
        width: 300px;
        height: 30px;
        background: sandybrown;
        line-height: 30px;
        text-align: center;
    }
    div {
        width: 260px;
        height: 160;
        background: antiquewhite;
        padding: 20px;
        display: none;
    }
</style>

<!-- html 部分 -->
<h4>鼠标经过&离开</h4>
<div>
    <p>相对论是关于时空和引力的基本理论,主要由阿尔伯特·爱因斯坦创立,依据研究的对象不同分为狭义相对论和广义相对论。相对论的基本假设是相对性原理,即物理定律与参照系的选择无关。</p>
</div>

<!-- js 部分 -->
<script>
    $(function() {
        $('h4').bind('mouseover', function() {
            $(this).next().show(600);
        }).bind('mouseout', function() {
            $(this).next().hide(300);
        });
    });
</script>

效果图:

image

我们可以看到,不管是show还是hide的时候,元素的不透明度都是在慢慢增加或者减小的。

8.2 fadeIn()方法 和 fadeOut()方法

showhide方法不同的是,fadeInfadeOut方法只改变元素的不透明度,不会去改变宽高。

下面的代码表示的是元素淡入的效果,其中也可以传时间:

$('element').fadeIn();

下面的代码表示的是元素淡出的效果:

$('element').fadeOut();

示例代码: [ 46-jq动画-fadeIn&fadeOut.html ]

 $(function() {
    $('h4').bind('mouseover', function() {
        $(this).next().fadeIn();
    }).bind('mouseout', function() {
        $(this).next().fadeOut();
    });
});

效果图:

image

8.3 slideUp()方法 和 slideDown()方法

slideUp()方法和slideDown()方法只会改变元素的高度,如果一个元素的display属性值为“none”,调用slideDown()方法的时候元素由上至下延伸显示。slideUp()正好相反,元素将由下到上缩短隐藏。

示例代码: [ 47-jq动画-slideDown&slideUp.html ]

 $(function() {
    $('h4').bind('mouseover', function() {
        $(this).next().slideDown();
    }).bind('mouseout', function() {
        $(this).next().slideUp();
    });
});

效果图:

image

8.4 自定义动画方法 animate()

前面几种类型动画,比较单一,很多时候不能满足于用户的需求,但是在jQ中还有一个自定义动画animate,非常强大。
animate(params,speed,easing,callback);

参数说明如下:

  • params:一个包含样式和值的对象,比如{p1:"val1",p2:"val2",...}
  • speed:动画执行速度(可选),默认400
  • easing:表示过度使用哪种缓动函数(默认swingjQ内部还支持一个linear)
  • callback:在动画执行完之后,执行的函数(可选)。

1、简单的动画:

<!-- 样式部分 -->
<style>
    #box {
        position: relative;
        width: 150px;
        height: 150px;
        background: aquamarine;
    }
</style>

<!-- html 部分 -->
<div id="box"></div>

<!-- js 部分 -->
<script>
    $(function() {
        // box两秒内向右移动600px
        $('#box').animate({left: '600px'}, 2000);
    });
</script>

效果图:

image

2、累加、累减动画:

通过累加一个值让元素从当前位置,累加到900的位置
$('#box2').animate({
    left: '+=900' // 在当前位置累加到 900
}, 1000);

3、多重动画:

同时执行多个动画

$('#box3').click(function() {
    $(this).animate({
        left: '300',
        height: '200px',
        width: '200px',
        top: '200px'
    }, 2000);
});

效果图:

image

我们可以看到所有的变化都是同时进行的。

按顺序执行多个动画

$('#box4').click(function() {
    $(this).animate({
        left: '400px',
        height: '150px',
        opacity: '1'
    }, 3000).animate({
        top: '150px',
        width: '150px'
    }, 3000).fadeOut('slow');
});

效果图:

image

4、延迟动画:

在动画执行中如果想要对某一段动画进行延迟操作,可以使用delay()方法。
$('#box5').click(function() {
    $(this).animate({
        left: '400px',
        height: '150px',
        opacity: '1'
    }, 3000)
    .delay(1000)
    .animate({
        top: '150px',
        width: '150px'
    }, 3000).fadeOut('slow');
});

效果图:

image

5、动画队列:

一组元素上的效果:

  • 当在一个animate()方法中应用多个属性时,动画是同时发生的;
  • 当以链式的写法应用到动画方法时,动画是按照顺序发生的。

多组元素上的动画:

  • 默认情况下,几组动画是同时发生的;
  • 当以回调形式应用动画方式时,动画按照回调顺序发生的。

6、停止动画:

如果需要在某处停止动画需要使用stop()方法。
stop([clearQueue],[gotoEnd]);

两个参数都是可选的,都为布尔值,clearQueue表示是否要清空未执行完的动画队列。gotoEnd表示的是直接将正在执行的动画跳转到末状态。直接使用stop()方法,则会立即停止当前正在执行的动画。

不明白的小伙伴,参考8.6小节,第二个案例 《动画下拉菜单栏》

8.5 其他动画方法

1、toggle()方法:

toggle()方法可以切换元素的可见状态,如果元素是可见的,则切换为隐藏。如果元素是隐藏的,则切换为可见。
$('#btn1').click(function() {
    $(this).next().toggle();
});

效果图:

image

只要循环点击h4,它的下一个兄弟元素就会循环切换。

2、slideToggle()方法:

通过高度变化来切换匹配元素的可见性。
$('#btn2').click(function() {
    $(this).next().slideToggle();
});

效果图:

image

3、fadeTo()方法:

fadeTo()方法可以将不透明度设置到指定的值。
$('#btn3').click(function() {
    $(this).next().fadeTo(600, 0.5);  // 600表示的是执行时间 0.5 表示目标值
});

效果图:

image

4、fadeToggle()方法:

fadeToggle()方法可以切换不透明度。
$('#btn4').click(function() {
    $(this).next().fadeToggle();
});

效果图:

image

8.6 jQuery 动画案例

下面通过几个简单的例子,巩固一下jQuery动画的知识。

1、呼吸灯版轮播图:

在实现原理上,与前面特效篇的是不同的,这里改变的是图片的不透明度opacity,并且不需要让所有li左浮动,ul也不需要设置一个很宽的宽度。在jQ中操作更加的简单。

样式上:

  • 大盒子相对定位,图片的li绝对定位,让所有的图片叠加在一起;
  • 给所有的图片li设置隐藏属性,第一张图片需要显示;

js上:

  • 定义一个index用来记录当前点击的张数;
  • 当点击右箭头的时候,让对应的图片lifadeIn,其余的兄弟元素fadeOut,同时让对应的小圆点添加current类,其余的兄弟元素移除这个类;
  • 点击左箭头只需将index--,再进行判断一下,其他的与点击右箭头原理是一样的。

示例代码: [ 50-jq动画-案例-呼吸灯版轮播图.html ]

<!-- 样式部分 -->
<style>
    * {
        margin: 0;
        padding: 0;
        list-style: none;
    }
    
    #slide {
        width: 560px;
        height: 315px;
        margin: 100px auto;
        position: relative;
    }
    
    #slide ul li {
        position: absolute;
        display: none;
    }
    
    #slide ul li:first-child {
        display: block;
    }
    
    #slide ul img {
        display: block;
    }
    
    #slide #arrow {
        display: none;
    }
    
    #slide:hover #arrow {
        display: block;
    }
    
    #slide #arrow #leftArr,
    #slide #arrow #rightArr {
        width: 30px;
        height: 60px;
        background-color: rgba(0, 0, 0, 0.3);
        position: absolute;
        top: 50%;
        margin-top: -30px;
        text-decoration: none;
        color: #fff;
        text-align: center;
        font: 700 24px/60px "宋体";
    }
    
    #slide #arrow #leftArr {
        left: 0;
    }
    
    #slide #arrow #rightArr {
        right: 0;
    }
    
    #slide #arrow #leftArr:hover,
    #slide #arrow #rightArr:hover {
        background-color: rgba(0, 0, 0, 0.5);
    }
    
    #slide ol {
        width: 100px;
        height: 14px;
        background-color: rgba(255, 255, 255, 0.6);
        position: absolute;
        bottom: 14px;
        left: 50%;
        margin-left: -50px;
        border-radius: 7px;
    }
    
    #slide ol li {
        width: 10px;
        height: 10px;
        float: left;
        background-color: #fff;
        border-radius: 50%;
        margin-top: 2px;
        margin-left: 8.5px;
        cursor: pointer;
    }
    
    #slide ol li.current {
        background-color: #DF654A;
    }
</style>

<!-- html 部分 -->
<div id="slide">
    <ul>
        <li>
            <a href="#"><img src="../image/轮播图/1.jpg" alt=""></a>
        </li>
        <li>
            <a href="#"><img src="../image/轮播图/2.jpg" alt=""></a>
        </li>
        <li>
            <a href="#"><img src="../image/轮播图/3.jpg" alt=""></a>
        </li>
        <li>
            <a href="#"><img src="../image/轮播图/4.jpg" alt=""></a>
        </li>
        <li>
            <a href="#"><img src="../image/轮播图/5.jpg" alt=""></a>
        </li>
    </ul>

    <div id="arrow">
        <a href="javascript:void(0);" id="leftArr">&lt;</a>
        <a href="javascript:void(0);" id="rightArr">&gt;</a>
    </div>

    <ol id="circleOl">
        <li class="current"></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ol>
</div>

<!-- js 部分 -->
<script>
    $(function() {
        // 定义一个变量,监测张数
        var index = 0;
        var $li = $('#slide ul li');
        // 1- 右箭头功能
        $('#rightArr').click(function() {
            index++;
            if (index == $li.length) {
                index = 0;
            }
            // 让第 index 个 li fadeIn,其他所有的兄弟元素 fadeOut
            $li.eq(index).fadeIn(1000).siblings().fadeOut(1000);
            // 控制小圆点,当前index的小圆点添加 current 类 其余的兄弟元素移除这个类
            $('#circleOl li').eq(index).addClass('current').siblings().removeClass('current');
        });
        // 2- 左箭头功能
        $('#leftArr').click(function() {
            index--;
            if (index == -1) {
                index = $li.length - 1;
            }
            // 让第 index 个 li fadeIn,其他所有的兄弟元素 fadeOut
            $li.eq(index).fadeIn(1000).siblings().fadeOut(1000);
            // 控制小圆点,当前index的小圆点添加 current 类 其余的兄弟元素移除这个类
            $('#circleOl li').eq(index).addClass('current').siblings().removeClass('current');
        });
    });
</script>

效果图:

image

2、动画下拉菜单栏:

动画下拉菜单栏,主要实现原理还是运用jQ里面的两个动画slideDownslideUp,并且配合stop方法

先看一下,如果不加stop()方法,会是一个什么效果:

image

我们可以看到一个效果,当光标移到第一个“一级菜单”的时候,触发动画效果,但是动画效果还没结束,我就将光标移进了第二个菜单,触发第二个菜单下拉效果。所以导致了动画效果与光标不一致,此时只需要在光标移入、移出之前加上stop()方法,就能解决这个问题。

stop()方法会结束当前正在进行的动画效果,并立即执行队列中的下一个动画。

示例代码: [ 51-jq动画-案例-动画下拉菜单.html ]

<!-- html 部分 -->
<div class="wrap">
    <ul>
        <li>
            <a href="javascript:void(0);">一级菜单1</a>
            <ul class="ul">
                <li><a href="javascript:void(0);">二级菜单11</a></li>
                <li><a href="javascript:void(0);">二级菜单12</a></li>
                <li><a href="javascript:void(0);">二级菜单13</a></li>
            </ul>
        </li>
        <li>
            <a href="javascript:void(0);">一级菜单2</a>
            <ul>
                <li><a href="javascript:void(0);">二级菜单21</a></li>
                <li><a href="javascript:void(0);">二级菜单22</a></li>
                <li><a href="javascript:void(0);">二级菜单23</a></li>
            </ul>
        </li>
        <li>
            <a href="javascript:void(0);">一级菜单3</a>
            <ul>
                <li><a href="javascript:void(0);">二级菜单31</a></li>
                <li><a href="javascript:void(0);">二级菜单32</a></li>
                <li><a href="javascript:void(0);">二级菜单33</a></li>
            </ul>
        </li>
    </ul>
</div>

<!-- js 部分 -->
<script>
    $(function() {
        // 1- 给当前 菜单栏注册鼠标进入事件
        $('.wrap>ul>li').mouseenter(function() {
            // 进入的时候,让下面的ul slideDown动画显示,显示之前要加上stop方法
            $(this).children('ul').stop().slideDown();
        });
        // 2- 给当前 菜单栏注册鼠标离开事件
        $('.wrap>ul>li').mouseleave(function() {
            // 离开的时候,让下面的ul slideUp动画显示,显示之前要加上stop方法
            $(this).children('ul').stop().slideUp()
        });
    });
</script>

效果图:

image

3、手风琴:

实现原理:

  • 给外部大盒子设置一个与图片大小一致的宽高,并且设置相对定位
  • 还是采用ul,li结构,li设置宽高,与图片大小一致,设置绝对定
  • 动态的给li添加背景图片,因为li绝对定位的原因,此时所有的li都叠在一起
  • 动态的给每个li设置left值(left*i),这时候li就会依次排开
  • 大盒子还要设置一个overflow-hidden属性,将多余的隐藏掉
  • 给每个li注册鼠标鼠标经过事件,然后根据下面推算出的规律(当前鼠标经过的索引index,他之前包括他自己的left值都是,设定的最小值乘以对应的索引。而他后面的会将设定的最小值乘以对应的索引后再加上450,这里的450不是一个固定值,根据规律找出来的)进行判断,设置各自的left值;
  • 鼠标离开的时候再让所有的盒子恢复到一开始的位置,每个li显示等分的宽度

大盒子没有overflow-hidden的时候:

image

画个图,理解一下:

image

找规律:

结合上面的图片,我们可以找到一个规律
  • 当鼠标在第1个li上的时候,li下标index为0:

    • index:0 left:0
    • index:1 left:500px
    • index:2 left:550px
    • index:3 left:600px
    • index:4 left:650px
  • 当鼠标在第2个li上的时候,li下标index为1:

    • index:0 left:0
    • index:1 left:50px
    • index:2 left:550px
    • index:3 left:600px
    • index:4 left:650px
  • 当鼠标在第3个li上的时候,li下标index为2:

    • index:0 left:0
    • index:1 left:50px
    • index:2 left:100px
    • index:3 left:600px
    • index:4 left:650px

看出规律了吗?

  • 当对应li的下标<=鼠标悬停的的下标上的时候left值 是50*i
  • 当对应li的下标>鼠标悬停的的下标上的时候left值 是50*i + ,450(450不是固定的值,是经过计算出来的)

示例代码: [ 52-jq动画-案例-手风琴.html ]

<!-- 样式部分 -->
<style>
    * {
        margin: 0;
        padding: 0;
        list-style: none;
    }
    
    #box {
        width: 700px;
        height: 440px;
        margin: 100px auto;
        position: relative;
        overflow: hidden;
        box-sizing: border-box;
        border-radius: 30px;
    }
    
    li {
        width: 700px;
        height: 440px;
        position: absolute;
    }
</style>

<!-- html 部分 -->
<div id="box">
    <ul>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
</div>

<!-- js 部分 -->
<script>
    $(function() {
        var $li = $('#box li');
        // 给所有的 li 设置背景图
        for (var i = 0; i < $li.length; i++) {
            // 这里加上eq的目的是,隐式迭代添加的图片只会是第一张
            $li.eq(i)
                .css({
                    "backgroundImage": "url(../image/手风琴/" + (i + 1) + ".png)",
                    "left": 140 * i
                });
            // 鼠标进入的时候
            $li.mouseenter(function() {
                for (var i = 0; i < $li.length; i++) {
                    // 判断i小于等于当前索引的时候,让之前的left值都是50*i的
                    if (i <= $(this).index()) {
                        $li.eq(i).stop().animate({
                            left: 50 * i
                        })
                    } else {
                        // 其余的li的left值应该加上450
                        $li.eq(i).stop().animate({
                            left: 50 * i + 450
                        });
                    }
                }
            });
            // 鼠标离开的时候 让每一个li 的left  恢复到 140*i
            $li.mouseleave(function() {
                for (var i = 0; i < $li.length; i++) {
                    $li.eq(i).stop().animate({
                        left: 140 * i
                    });
                }
            });
        }
    });
</script>

效果图:

image

4、弹幕效果:

  • 获取输入框的的 value 值;并生成 span 标签
  • span 标签添加到 页面中,随机颜色 随机高度 span动画从右向左
  • 到达最左边的时候删除 span 标签(不删除会随着输入的内容越来越多影响性能)

示例代码: [ 53-jq动画-案例-弹幕效果.html ]

<!-- html 部分 -->
<div id="page">
    <div id="import">
        <div id="content">
            <p class="title">吐槽</p>
            <input type="text" name="" id="text" placeholder="发送弹幕,与小伙伴一起互动!">
            <button id="btn">发射</button>
        </div>
    </div>
</div>

<!-- js 部分 -->
<script>
    $(function() {
        // 定义一个颜色数组
        var colorArr = ['#FF895D', '#78BBE6', '#FF4273', '#00BBF0', '#7C73E6', '#EE2B47', '#F60C86', '#9870FC', '#F96D00', '#303481'];

        $('#btn').click(function() {
            // 获取到输入框的内容
            var content = $('#text').val();
            $("#text").val("");

            // 获取随机颜色和高度
            var randomColor = parseInt(Math.random() * colorArr.length);
            var randomTop = parseInt(Math.random() * 301);
            // 获取屏幕的可视宽度
            var clientWidth = $(window).width();
            // 根据屏幕的宽度计算出弹幕的速度(1300px的时候8秒执行完)
            var time = (8000 / 1300) * clientWidth;
            // 创建span标签 判断当输入为空的时候不触发
            if (content != "" && content.trim()) {
                $('<span></span>').text(content)
                    // 设置span的颜色 与 top值left值 
                    .css({
                        "color": colorArr[randomColor],
                        "left": clientWidth,
                        "top": randomTop
                    })
                    // 将创建的span添加到页面中
                    .appendTo("#page")
                    // 执行动画 left目标值-300px,执行时间time 过渡效果linear(匀速) 回调函数内将到达终点的span移除掉
                    .animate({left: -300}, time, "linear", function() {
                        $(this).remove();
                    })
            }
        });
        // 对整个页面注册键盘按下事件
        $(document).keydown(function(e) {
            // 当按下的键为回车键时,执行上面的点击事件
            if (e.keyCode == 13) {
                $("#btn").click();
            }
        })
    });
</script>

效果图:

image

9. jQuery 里的 Ajax 操作

Ajax全称“Asynchronous JavaScript and XML”(异步的JavaScriptXML)。它的出现揭开了无刷新更新页面的新时代。具体的实现方式以及Ajax的优缺点,在前面的一篇文章[《js 进阶知识-Ajax篇》]()已经讲得很详细了,不明白的小伙伴,可以先去学习下原生js是如何实现Ajax的。

jQueryAjax操作进行了封装,在jQuery$.ajax()方法属于最底层的方法,第2层是load()$.get()$.post()方法,第3层就是$.getScript()$.getJSON()方法。

9.1 load()方法

1、载入HTML文档

load()方法是jQuery中最为简单和常用的Ajax方法,能载入远程HTML代码并插入DOM中。它的结构为:
load(url[,data][,callback]);

参数详解:

参数名称 类型 说明
url String 请求HTML页面的URL地址
data(可选) Object 发送至服务器的key/value数据
callback(可选) Function 请求完成时的回调函数,无论请求成功还是失败

示例代码:

首先新建一个data.html的文件,里面模拟的是请求的数据:

<div class="comment">
    <h4>张三:</h4>
    <p class="para">哈哈哈,真有趣</p>
</div>
<div class="comment">
    <h4>李四:</h4>
    <p class="para">顶楼上</p>
</div>
<div class="comment">
    <h4>王五:</h4>
    <p class="para">66666</p>
</div>

再创建一个主页面,index.html

<!-- 样式部分 -->
<style>
    .send {
        margin-bottom: 10px;
    }
    
    .comment {
        width: 300px;
        padding: 10px 0px 10px 10px;
        background: rgba(156, 250, 220, 0.5);
        border: 1px dashed #f45;
        margin-bottom: 10px;
    }
</style>

<!-- html 部分 -->
<input type="button" class="send" value="Ajax请求">
<div class="comment">已有评论:</div>
<div class="resText"></div>

<!-- js部分 -->
<script>
    $(function() {
        // 点击按钮,使用load方法请求data页面
        $(".send").click(function() {
            // 请求的页面追加到类名为resText的div中
            $(".resText").load("data.html");
        });
    });
</script>

效果图:

image

上面的例子可以看出来,开发人员只需要使用jQuery选择器为HTML片段指定目标位置,然后将要加载的文件URL作为参数传递给load()方法即可。我们可以发现原本的data页面是没有为类comment设置样式的,但是主页面加载后同样的样式名会立即应用到新加载的内容上。

2、筛选载入的HTML文档

上面的案例我们可以看到,点击之后data.html里面的整个内容都被加载进来了。如果需要加载data.html页面里的某些元素的时候该怎么办呢?我们可以使用load()方法的URL参数来达到目的。只需要指定选择符就ok了。

示例代码:

// 选择加载data.html页面中class为“para”的内容,注意中间有一个空格
$(".resText").load("data.html .para");

效果图:

image

我们可以看到,只有类名是“para”的被加载了。

3、传递方式:

load()方法的传递方式根据参数data来自动指定。如果没有参数传递,则采用GET方式传递;反之则会自动转换为POST方式:
// 1- 无data参数传递的时候,则是GET方式
$('.resText').load("data.php",function(){});

// 2- 有data参数传递的时候,则是POST方式
$('.resText').load("data.php",{name:"Levi",age:"18"},function(){});

4、回调函数:

回调函数是在页面加载完成之后执行的操作,该函数有三个参数,分别是请求返回的内容、请求状态、XMLHttpRequest对象:
$('.resText').load("data.php",function(responseText,textStatus,XMLHttpRequest){
    // responseText : 请求返回的内容
    // textStatus:请求状态:success、error、notmodified、timeout 4种
    // XMLHttpRequest :XMLHttpRequest对象
});

load()方法中,无论Ajax请求是否成功,只要当请求完成之后,回调函数都会执行。

9.2 $.get()方法和$.post()方法

load()方法通常是用来从WEB服务器上获取静态的数据的,如果需要向服务器传递参数的话,可以使用$.get()方法和$.post()方法还有后面的$.ajax方法。

1、$.get()方法

$.get()方法使用GET方式来进行异步请求:
$.get(url [,data] [,callback] [,type]);

参数详解:

参数名称 类型 说明
url String 请求HTML页面的URL地址
data(可选) Object 发送至服务器的key/value数据,会作为字符串凭接在url的后面
callback(可选) Function 请求完成时的回调函数(只有当Response的返回状态是success的时候,才调用该函数)
type (可选) String 服务器返回内容的格式,包括xml、html、script、json、text、_default

回调函数:

$.get()方法的回调函数只有两个参数:
$.get("get.php",{useraname: "Levi",age:18},function(data,textStatus){
    // data 返回的内容,可以是XML文档、JSON文件、HTML片段等的
    // textStatus 请求状态:success、error、notmodified、timeout 4种。
})

data参数代表请求返回的内容,textStatus参数代表请求回来的状态,注意:只有当数据成功返回success后才被调用。

2、$.post()方法

它与$.get()方法的结构和使用方式都相同,不过他们之间仍有以下区别:
  • get请求会将参数跟在URL的后面进行传递,而post请求则是作为HTTP消息的实体内容发送给Web服务器;
  • get对传输的数据大小有限制(通常不大于2KB),而使用post方式传递数据量要比get方式大得多;
  • get方式请求的数据会被浏览器缓存起来,因此可以通过浏览器的历史记录中读到这些数据,存在安全性问题。

9.3 $.ajax()方法

$.ajax()方式常用参数解析:
方法 作用
url 请求的地址
type 请求的方式
dataType 告诉jQuery,需要按照什么格式对服务器返回的数据进行解析,默认json
data 数据
success 请求成功的回调函数
error 请求失败的回调函数
beforeSend 请求发送之前调用的函数
complete 不论请求是成功还是失败的,只要请求完成就会调用
timeout 设置请求超时时间

示例代码:

$.ajax({
    // 请求的地址
    url: "04-data.php",
    // 请求的方式
    type: "get",
    // 告诉jQuery,需要按照什么格式对服务器返回的数据进行解析,默认json
    dataType: "json",
    // 数据
    data: {
        msg: "我是来请求数据的"
    },
    // 请求成功的回调函数
    success: function(data) {
        console.log(data);
    },
    // 请求失败的回调函数
    error: function() {
        console.log("失败了");
    },
    // 请求发送之前调用的函数
    beforeSend: function() {
        console.log("请求发送之前调用的函数");
        // 如果返回一个false,那么就会阻止整个请求的发送
        // return false;
        // 用法:可以用作表单验证,当表单内容符合规范的时候发送ajax请求,当不符合的时候就不发送ajax请求
    },
    // 不论请求是成功还是失败的,只要请求完成就会调用
    complete: function() {
        console.log("请求完成了");
    },
    // 设置请求超时时间(单位:ms),超过这个时间后,就不会请求了
    timeout:2000
});

9.3 jQuery中的serialize和serializeArray方法

1、jQuery中的serialize方法:

serialize方法会将表单中所有的内容拼接成key=value&key=value这样的字符串。

通过这种方式就不要再去手动获取表单中的内容的

<form id="form">
    <input type="text" name="username">
    <input type="text" name="pwd">
    <input type="text" name="phonenumber">
    <input type="text" name="email">

    <button id="btn">获取数据</button>
</form>

<script src="jquery.min.js"></script>
<script>
    $(function() {
        $('#btn').click = function() {
            var dataStr = $('#form').serialize();
            $.ajax({
                url: "json.php",
                //data这个参数可以接收对象,也可以接受 key=value&key=value的这种字符串
                data: dataStr,
                type: "post"
            });
        }
    });
</script>

2、jQuery中的serializeArray方法:

上面的方法我们可以看到,获取整个数据的时候,是很简单,但是想要进行校验的话就很难,因为上面的方法获取的是一个字符串,不能进行校验,所以此时我们需要另外一个方法,jQuery中的serializeArray方法。
<form id="form">
    <input type="text" name="username">
    <input type="text" name="pwd">
    <input type="text" name="phonenumber">
    <input type="text" name="email">

    <button id="btn">获取数据</button>
</form>

<script src="jquery.min.js"></script>
<script>
    $(function() {
        $('#btn').click = function() {
            // 获取到的数组拼接成字符串
            var dataArr = $('#form').serializeArray();
            $.ajax({
                url: "json.php",
                data: dataArr,
                type: "post"
            });
        }
    });
</script>

示例代码:ajax模拟表单校验及注册

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>sing in page</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            background-color: #F7F7F7;
        }
        
        ul {
            margin: 0;
            padding: 50px;
            list-style: none;
        }
        
        .register {
            width: 800px;
            margin: 50px auto;
            background-color: #FFF;
            border: 1px solid #CCC;
            border-radius: 5px;
        }
        
        li {
            display: flex;
            margin: 20px 0;
        }
        
        label,
        input {
            display: block;
            float: left;
            height: 46px;
            font-size: 24px;
            box-sizing: border-box;
            color: #333;
        }
        
        label {
            width: 200px;
            line-height: 46px;
            margin-right: 30px;
            text-align: right;
        }
        
        input {
            width: 320px;
            padding: 8px;
            line-height: 1;
            outline: none;
            position: relative;
        }
        
        input.code {
            width: 120px;
        }
        
        input.verify {
            width: 190px;
            margin-left: 10px;
        }
        
        input.disabled {
            background-color: #CCC !important;
        }
        
        input[type=button] {
            border: none;
            color: #FFF;
            background-color: #E64145;
            border-radius: 4px;
            cursor: pointer;
        }
        
        .error {
            color: red;
            margin-left: 10px;
            font-size: 12px;
            line-height: 46px;
        }
        
        .tips {
            position: fixed;
            top: 0;
            width: 100%;
            height: 40px;
            text-align: center;
        }
        
        .tips p {
            min-width: 300px;
            max-width: 400px;
            line-height: 40px;
            margin: 0 auto;
            color: #FFF;
            display: none;
            background-color: #C91623;
        }
    </style>
</head>

<body>
    <div class="register">
        <form id="ajaxForm">
            <ul>
                <li>
                    <label for="name">用户名</label>
                    <input type="text" name="name" class="name" id="name">
                    <span class="error"></span>
                </li>
                <li>
                    <label for="pass">请设置密码</label>
                    <input type="password" name="pass" class="pass" id="pass">
                </li>
                <li>
                    <label for="repass">请确认密码</label>
                    <input type="password" name="repass" class="repass" id="repass">
                </li>
                <li>
                    <label for="mobile">验证手机</label>
                    <input type="text" name="mobile" class="mobile" id="mobile">
                </li>
                <li>
                    <label for="code">短信验证码</label>
                    <input type="text" name="code" class="code" id="code">
                    <input type="button" value="获取验证码" class="verify">
                </li>
                <li>
                    <label for="submit"></label>
                    <input type="button" class="submit" value="立即注册" id="submit">
                </li>
            </ul>
        </form>
    </div>
    <div class="tips">
        <p>用户名不能为空</p>
    </div>

    <script src="../05-Form-Validation/js/jquery.min.js"></script>
    <script>
        /*
         * 1.获取短信验证码
         * 1.1 当没有输入手机号的时候  提示请输入手机号
         * 1.2 手机号格式不正确        提示请输入正确的手机号
         * 1.3 调获取短信验证码接口
         * 1.4 显示正在发送中  不能再次发送(防止重复提交)
         * 1.5 当接口成功  按照后台的计时时间  进行倒计时
         * 1.6 当接口失败  提示短信接口繁忙 恢复按钮
         * 1.7 倒计时完成之后  恢复按钮
         * */

        /*
         * 2.注册
         * 2.1 当没有输入用户名的时候  提示请输入用户名
         * 2.2 调注册接口
         * 2.3 显示正在提交 不能再次发送(防止重复提交)
         * 2.4 当接口成功
         *     状态码 10000 成功
         *     状态码 10001 失败 提示用户  用户名已注册  表单后
         *     状态码 10002 失败 没输用户  请输入用户名
         *     恢复按钮
         * 2.5 当接口失败  恢复按钮
         * */
        $(function() {
            /* 警告显示提示 */
            var showTip = function(tip) {
                $(".tips p").html(tip).fadeIn(500).delay(1000).fadeOut(500);
            };

            /* 1.获取短信验证码 */
            $(".verify").on("click", function() {
                /* 当前按钮指定变量 */
                var $btn = $(this);
                /* 判断当前按钮是否有disabled属性,有的话说明已经被点击了,就不让再点击了 */
                if ($btn.hasClass('disabled')) {
                    return false;
                }

                /* 获取手机号 */
                var mobile = $.trim($('#mobile').val());
                /* 判断是否输入内容,没有的话提示信息 */
                if (!mobile) {
                    showTip('请输入手机号');
                    return false;
                }
                /* 判断手机格式 不正确的话提示信息 */
                var regPhone = /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/;
                if (!regPhone.test(mobile)) {
                    showTip('请输入正确的手机号');
                    return false;
                }
                /* 调取短信验证码接口 */
                $.ajax({
                    url: 'registerCode.php',
                    type: 'post',
                    dataType: 'json',
                    data: {
                        mobile: mobile
                    },
                    success: function(data) {
                        if (data.code == 10000) {
                            /* 给发送成功的按钮添加一个倒计时 */
                            var time = parseInt(data.result.time);
                            var timer = setInterval(function() {
                                time--;
                                $btn.val(time + '秒后再次获取');
                                /* 倒计时完成之后  恢复按钮*/
                                if (time <= 0) {
                                    $btn.val('获取验证码').removeClass('disabled');
                                    clearInterval(timer);
                                }
                            }, 1000);
                        } else {
                            /* 逻辑上的失败 */
                            $btn.val('获取验证码').removeClass('disabled');
                        }
                    },
                    error: function() {
                        /* 当接口失败,提示短信接口繁忙 */
                        showTip('短信接口繁忙');
                        $btn.val('获取验证码').removeClass('disabled');
                    },
                    beforeSend: function() {
                        /* 点击之后,显示正在发送 */
                        $btn.val('正在发送...').addClass('disabled');
                    }
                });
                $btn.addClass('disabled');
            });
            /* 2.注册功能的实现 */
            $('.submit').on('click', function() {
                /* 当前点击的按钮 */
                var $btn = $(this);
                /* 正在请求当中 不能再次点击 */
                if ($btn.hasClass('disabled')) {
                    return false;
                }
                var username = $("#name").val().trim();
                var password = $("#pass").val().trim();
                var repeatPassword = $("#repass").val().trim();
                var code = $("#code").val().trim();
                var phoneNum = $("#mobile").val().trim();

                /* 调注册接口 */
                $.ajax({
                    type: 'post',
                    url: 'register.php',
                    data: {
                        name: username,
                        pass: password,
                        repass: repeatPassword,
                        code: code,
                        mobile: phoneNum
                    },
                    dataType: 'json',
                    // beforeSend: function() {
                    //     /* 显示正在提交 不能再次发送(防止重复提交)*/
                    //     $btn.val('正在提交...').addClass('disabled');
                    // },
                    success: function(data) {
                        /* 当接口成功 */
                        /* 状态码 10000 成功 */
                        if (data.code == 10000) {
                            /* 提示+跳转登录页 */
                            showTip('恭喜' + data.result.name + '注册成功,3后秒自动前往登录页');
                            setTimeout(function() {
                                location.href = 'http://www.baidu.com/';
                            }, 3000);
                        } else if (data.code == 10001) {
                            /* 输入框提示 */
                            $('.error').html('用户名已注册');
                            /* 恢复按钮 */
                            $btn.val('立即注册').removeClass('disabled');
                        } else if (data.code == 10002) {
                            showTip('请输入用户名');
                            /* 恢复按钮 */
                            $btn.val('立即注册').removeClass('disabled');
                        }
                    },
                    error: function() {
                        showTip('系统繁忙!');
                        $btn.val('立即注册').removeClass('disabled');
                    }
                })
            });
        });
    </script>
</body>

</html>

效果图:

image

10. jQuery 插件的使用

插件:pluginjQuery不可能包含所有的功能,所以就出现了成百上千的插件,帮助我们扩展jQuery的功能。

最新最全的插件可以参考jQuery官方网站的插件版块

10.1 颜色插件-jQuery.color.js

animate不支持颜色的渐变,但是使用了jquery.color.js后,就可以支持颜色的渐变了。

使用步骤:

  • 先引入jQuery,再引入jquery.color.js
  • 使用插件
<!-- 引入js -->
<script src="../js/jquery-3.2.1.min.js"></script>
<script src="../js/plugins/jquery.color.js"></script>

<!-- 样式部分 -->
<style>
    .box {
        width: 300px;
        height: 300px;
        background: aquamarine;
    }
</style>

<!-- html 部分 -->
<input type="button" id="btn" value="点击过渡">
<div class="box"></div>

<!-- js 部分 -->
<script>
    $(function() {
        $('#btn').click(function() {
            $('.box').animate({
                backgroundColor: "#f45f45"
            }, 1000);
        });
    });
</script>

10.2 懒加载插件- jquery.lazyload.js

什么是懒加载?

懒加载也就是延迟加载。当访问一个页面的时候,先把img元素或是其他元素的背景图片路径替换成一张大小为1*1px图片的路径(这样就只需请求一次,俗称占位图),只有当图片出现在浏览器的可视区域内时,才设置图片正真的路径,让图片显示出来。这就是图片懒加载。

为什么要使用懒加载?

很多页面,内容很丰富,页面很长,图片较多。比如说各种商城页面。这些页面图片数量多,而且比较大,少说百来K,多则上兆。要是页面载入就一次性加载完毕。估计大家都会等到黄花变成黄花菜了。

懒加载的原理是什么?

页面中的img元素,如果没有src属性,浏览器就不会发出请求去下载图片,只有通过javascript设置了图片路径,浏览器才会发送请求。

懒加载的原理就是先在页面中把所有的图片统一使用一张占位图进行占位,把正真的路径存在元素的“data-url”(这个名字起个自己认识好记的就行)属性里,要用的时候就取出来,再设置;

懒加载的实现步骤?

首先,不要将图片地址放到src属性中,而是放到其它属性(data-url)中。

页面加载完成后,根据scrollTop判断图片是否在用户的视野内,如果在,则将data-url属性中的值取出存放到src属性中。

在滚动事件中重复判断图片是否进入视野,如果进入,则将data-url属性中的值取出存放到src属性中。

插件使用:

  • 首先,这里图片的自定义属性就要用data-original
  • jQ中找到图片元素,给它加上一个lazyload()函数。
<!-- 样式部分 -->
<style>
    center {
        margin-top: 1200px;
    }
    
    div {
        margin-bottom: 10px;
    }
    
    img {
        width: 500px;
        height: 350px;
    }
</style>

<!-- html 部分 -->
<center id="box">
    <div><img src="" data-original="http://ww1.sinaimg.cn/large/9c47d583gy1fjgqik3k1kj211y0lcdji.jpg" alt="当你看不见图片的时候,你才会看到这里的字"></div>
</center>

<!-- js 部分 -->
<script>
    $(function() {
        //使用插件
        $("img").lazyload();
    });
</script>

10.3 jQuery UI 插件

jQuery UI 是一个建立在 jQuery JavaScript 库上的小部件和交互库,您可以使用它创建高度交互的 Web 应用程序。

下载地址:点击这里跳转到官网下载

10.4 jQuery自定义插件

虽然网上的插件有很多,但是可能不是我们完全想要的,其中可能还穿插着其他的功能,所以我们也可以自己封装一个jQuery插件,

有三种方式为所有jQuery对象添加方法,在创建一个jQuery插件的时候,我们只需要将添加的方法保存为一个js文件,再去引用它即可。

1、$.prototype方法添加

$.prototype.setStyle = function(){

};

2、$.fn.setStyle方法添加

        $.fn.setStyle = function(){

        };

3、$.fn.extend({})方法添加

// extend可以新增多个方法
$.fn.extend({
    setStyle:function(){

    },
    setPosition:function(){
        
    }
});

示例代码:

通过上面三种方法的任何一种,为jQuery添加一个插件setStyle

创建插件jquery.setStyle.js

// 给jQuery里面添加一个setStyle方法
// (function(){})()的作用是函数自调用,避免全局污染。是一种设计模式:沙箱模式
(function(){
    $.fn.setStyle = function(){
        this.css({
            width:400,
            height:400,
            backgroundColor:"pink"
        });
        return this;
    }

})()

使用插件:

<div id="box"></div>

<script src="jquery.min.js"></script>
<script src="jquery.setStyle.js"></script>
<script>
    // 弹出123
    $("#box").setStyle();
</script>

沙箱模式(function(){})()的作用是函数自调用,避免全局污染。是一种设计模式:沙箱模式

10.5 jQuery自定义插件-瀑布流插件

jQuery封装一个瀑布流插件,前面特效篇已经讲过了瀑布流的原理,不明白的小伙伴,建议先去看看原生实现的原理(《原生js实现瀑布流效果》),再来学习jQuery封装。

主页面部分:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>瀑布流</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            font-family: "Microsoft Yahei";
            background: #f5f5f5;
        }
        .box {
            width: 1200px;
            margin: 0 auto;
            padding-top: 40px
        }
        .box > .items {
            position: relative;
        }
        .box > .items > .item {
            width: 220px;
            box-shadow: 2px 2px 2px #999;
            position: absolute;
        }
        .box > .items > .item > p {
            margin: 0;
            padding: 10px;
            background: #fff;
        }
        .box > .items > .item > img {
            width: 100%;
            display: block
        }
        .box > .btn {
            width: 280px;
            height: 40px;
            margin: 30px auto;
            text-align: center;
            line-height: 40px;
            background-color: #CCC;
            border-radius: 6px;
            font-size: 24px;
            cursor: pointer;
        }
        .box > .loading {
            background-color: transparent;
        }
        
    </style>
</head>

<body>
    <div class="box">
        <div class="items">
            <div class="item">
                <img src="image/001.jpg" alt="">
                <p>云想衣裳花想容,春风拂槛露华浓。若非群玉山头见,会向瑶台月下逢。</p>
            </div>
                    .
                    .
                    .
            <div class="item">
                <img src="image/030.jpg" alt="">
                <p>云想衣裳花想容,春风拂槛露华浓。若非群玉山头见,会向瑶台月下逢。</p>
            </div>

        </div>
        <div class="btn">正在加载...</div>
    </div>

    <script src="jquery.min.js"></script>
    <script src="jquery.waterfull.js"></script>
    <script>
        // 一定要写在入口函数内,保证图片加载完在计算高度
        window.onload = function(){
            $(".items").waterfull();
        }
    </script>
</body>

</html>

封装插件jquery.waterfull.js:

(function(){
    $.fn.waterfull = function(){
        // 1-确定要排多少列
        var columns = 5;

        // 2-获取每一个元素的宽度
        // this指的是当前调用的对象items 要获取的是item的宽度
        var width = this.children().width();

        // 3-计算间隔 gap:左右间隔 gap_t:上下间隔
        var gap = (this.width() - width * columns) / (columns - 1);
        var gap_t = 10;
        // 4-声明一个数组,用来存放所有item的高度值
        var heightArr = [];
        
        // 5-遍历所有item
        this.children().each(function(index,ele){
            // 5-1 排列第一行
            // 判断当前遍历的item索引小于列数的时候,说明是第一行
            if(index < columns){
                // 将ele对象转化成DOM对象,再设置它的top 和 left
                $(ele).css({
                    top:0,
                    left:index * (width +gap)
                });
                // 5-2 将第一行每一个item的高度存到数组中
                heightArr.push($(ele).height());
            }else{
                // 5-3 计算heightArr数组里面的最小值,并记录下最小值的列数即索引
                var minHeight = heightArr[0];
                var minIndex = 0;
                $.each(heightArr,function(index,value){
                    if(minHeight > value){
                        minHeight = value;
                        minIndex = index;
                    }
                });

                // 5-5 当剩下的item排在最小列下面的时候,要在数组中,跟新这个最小列的高度
                heightArr[minIndex] += $(ele).height() + gap_t;
 
                // 5-4 排列剩下的行数,下面的item放到上一行最小高度的下面,依次列推
                // 设定定位的top值, 10 是上下的间距
                var top = minHeight + gap_t;
                // 设定定位的left值,即高度最小列的索引乘以item的宽度加上间隙
                var left = minIndex * (width + gap);
                $(ele).css({
                    top: top,
                    left: left
                });
            }
            
            // 6-设置加载按钮的位置,只需要将items设置一个高度即可
            // 加载按钮的位置应该在heightArr数组里最大高度值的哪一个item的下面
            var maxHeight = heightArr[0];
            $.each(heightArr,function(index,value){
                maxHeight = maxHeight > value ? maxHeight : value;
            });
            // 设置items的高度 this指的是每一个item
            $(this).parent().height(maxHeight);
        })
    }
})()

上一篇:jQuery 入门详解(一)


深海丶Deepsea
3.9k 声望1.4k 粉丝

Trust yourself,You know more than you think you do.