今天更新完
部分转自https://www.liaoxuefeng.com/wiki
概述
- JavaScript 库
JavaScript库:即 library,是一个封装好的特定的集合(方法和函数)。从封装一大堆函数的角度理解库,就是在这个库中,封装了很多预先定义好的函数在里面,比如动画animate、hide、show,比如获取元素等。
简单理解: 就是一个JS 文件,里面对我们原生js代码进行了封装,存放到里面。这样我们可以快速高效的使用这些封装好的功能了。
比如 jQuery,就是为了快速方便的操作DOM,里面基本都是函数(方法)。
常见的JavaScript 库:jQuery、Prototype、YUI、Dojo、Ext JS、移动端的zepto等,这些库都是对原生 JavaScript 的封装,内部都是用 JavaScript 实现的。
- jQuery
是一个快速、简洁的 JavaScript 库,其设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。 j 就是 JavaScript; Query 查询; 意思就是查询js,把js中的DOM操作做了封装,我们可以快速的查询使用里面的功能。
jQuery 封装了 JavaScript 常用的功能代码,优化了 DOM 操作、事件处理、动画设计和 Ajax 交互。jQuery 是基于 Javascript 构造函数的原型对象实现的,通过为原型对象添加属性或方法的方式实现对DOM 操作的封装。 - jQuery的优点
- 轻量级。核心文件才几十kb,不会影响页面加载速度。
- 跨浏览器兼容,基本兼容了现在主流的浏览器。消除浏览器差异:你不需要自己写冗长的代码来针对不同的浏览器
- 链式编程、隐式迭代。
- 对事件、样式、动画支持,大大简化了DOM操作。简洁的操作DOM的方法:写$(‘#test’)肯定比document.getElementById(‘test’)来得简洁;
- 支持插件扩展开发。有着丰富的第三方的插件,例如:树形菜单、日期控件、轮播图等。轻松实现动画、修改CSS等各种操作。
- 免费、开源。
使用
- jQuery 的下载
jQuery的官网地址: https://jquery.com/,官网即可下载最新版本。
各个版本的下载:https://code.jquery.com/
版本介绍:
1x :兼容 IE 678 等低版本浏览器, 官网不再更新2x :不兼容 IE 678 等低版本浏览器, 官网不再更新
3x :不兼容 IE 678 等低版本浏览器, 是官方主要更新维护的版本
通常下载 jQuery 时需要有 3 个文件,分别为:
jquery-版本号.js
jquery-版本号.min.js
jquery-版本号.min.map
其中 jquery-版本号.js 与 jquery-版本号.min.js 内部分代码是一致的,区别仅仅是 jquery-版本号.min.js 中不包含注释、换行、缩进等,甚至变量名也被处理成单个字母形式,这样做的目的是压缩代码量,使文件体积变小。
jquery-版本号.min.map 是官方在压缩代码时自动生成的一个文件,该文件中记录了 jquery 压缩前后的对应关系,浏览器调试时能够快速定位到出错代码的位置。
多库共存
实际开发中,很多项目连续开发十多年,jQuery版本不断更新,最初的 jQuery 版本无法满足需求,这时就需要保证在旧有版本正常运行的情况下,新的功能使用新的jQuery版本实现,这种情况被称为,jQuery 多库共存。
需要一个解决方案,让jQuery 和其他的js库不存在冲突,可以同时存在
插件
这些插件也是依赖于jQuery来完成的,所以必须要先引入jQuery。
jQuery 插件常用的网站:
jQuery 插件库 http://www.jq22.com/
jQuery 之家 http://www.htmleaf.com/ 如瀑布流、图片懒加载、全屏滚动
bootstrap组件:bootstrap是基于jQuery实现的框架,包含很多插件。
jQuery 插件使用步骤:
引入相关文件。(jQuery 文件 和 插件文件)
复制相关html、css、js (调用插件)。
使用操作
每次调用 jQuery 或 $ 函数都会得到一个新的实例。
- 步骤:
引入jQuery文件。
在文档最末尾插入 script 标签,书写代码。
$(‘div’).hide() 可以隐藏盒子。 - jQuery中常见的两种入口函数:
// 第一种: 简单易用。
$(function () {
... // 此处是页面 DOM 加载完成的入口
}) ;
// 第二种: 繁琐,但是也可以实现
$(document).ready(function(){
... // 此处是页面DOM加载完成的入口
});
总结:
- 等着 DOM 结构渲染完毕即可执行内部代码,不必等到所有外部资源加载完成,jQuery 帮我们完成了封装。
- 相当于原生 js 中的 DOMContentLoaded。
- 不同于原生 js 中的 load 事件是等页面文档、外部的 js 文件、css文件、图片加载完毕才执行内部代码。
- 更推荐使用第一种方式。
<html>
<head>
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
...
</head>
<body>
...
</body>
</html>
//jQuery把所有功能全部封装在一个全局变量jQuery中
//$也是一个合法的变量名,它是变量jQuery的别名:
window.jQuery; // jQuery(selector, context)
window.$; // jQuery(selector, context)
$ === jQuery; // true
typeof($); // 'function'
//$本质上是一个函数,但函数也是对象
//于是$除了可以直接调用外,也可以有很多其他属性。
//JavaScript压缩工具可以对函数名和参数改名,所以压缩过的jQuery源码$函数可能变成a(b, c)
//如果$这个变量不幸地被占用了,而且还不能改,那我们就只能让jQuery把$变量交出来,然后就只能使用jQuery这个变量:
$; // jQuery(selector, context)
jQuery.noConflict();
$; // undefined
jQuery; // jQuery(selector, context)
- jQuery中的顶级对象$
- $是 jQuery 的别称,在代码中可以使用 jQuery 代替,但一般为了方便,通常都直接使用 $ 。
$
是jQuery的顶级对象,相当于原生JavaScript中的 window。把元素利用$包装成jQuery对象,就可以调用jQuery 的方法。
- jQuery 对象和 DOM 对象
什么是jQuery对象?jQuery对象类似数组,它的每个元素都是一个引用了DOM节点的对象。
使用 jQuery 方法和原生JS获取的元素是不一样的,总结如下 :
- 用原生 JS 获取来的对象就是 DOM 对象
- jQuery 方法获取的元素就是 jQuery 对象。
- jQuery 对象本质是: 利用$对DOM 对象包装后产生的对象(伪数组形式存储)。
注意:只有 jQuery 对象才能使用 jQuery 方法,DOM 对象则使用原生的 JavaScirpt 方法。
- jQuery 对象和 DOM 对象转换
实际开发比较常用的是把DOM对象转换为jQuery对象,这样能够调用功能更加强大的jQuery中的方法。
DOM 对象与 jQuery 对象之间是可以相互转换的。因为原生js 比 jQuery 更大,原生的一些属性和方法 jQuery没有给我们封装. 要想使用这些属性和方法需要把jQuery对象转换为DOM对象才能使用。
// 1.DOM对象转换成jQuery对象,方法只有一种
var box = document.getElementById('box'); // 获取DOM对象
var jQueryObject = $(box); // 把DOM对象转换为 jQuery 对象
// 2.jQuery 对象转换为 DOM 对象有两种方法:
// 2.1 jQuery对象[索引值]
var domObject1 = $('div')[0]
// 2.2 jQuery对象.get(索引值)
var domObject2 = $('div').get(0)
选择器
jQuery的选择器就是帮助我们快速定位到一个或多个DOM节点。选择器:jQuery通过元素的选择器获取元素、注意jQuery获取的是伪数组形式的,称为jQuery的对象。通过 jQuery 选择器获取 DOM 节点的同时也得到了一个 jQuery 实例
- 基础选择器
$("选择器") // 里面选择器直接写 CSS 选择器即可,但是要加引号
- 层级选择器
最常用的两个分别为:后代选择器和子代选择器。
- 筛选选择器
parents()
祖先元素
next
prev
var ul = $('ul.lang'); // 获得<ul>
var dy = ul.find('.dy'); // 获得JavaScript, Python, Scheme
var swf = ul.find('#swift'); // 获得Swift
var hsk = ul.find('[name=haskell]'); // 获得Haskell
var swf = $('#swift'); // 获得Swift
var parent = swf.parent(); // 获得Swift的上层节点<ul>
var a = swf.parent('.red'); // 获得Swift的上层节点<ul>,同时传入过滤条件。如果ul不符合条件,返回空jQuery对象
对于位于同一层级的节点,可以通过next()和prev()方法,
var swift = $('#swift');
swift.next(); // Scheme
swift.next('[name=haskell]'); // 空的jQuery对象,因为Swift的下一个元素Scheme不符合条件[name=haskell]
swift.prev(); // Python
swift.prev('.dy'); // Python,因为Python同时符合过滤器条件.dy
$(function() {
console.log($(".nav"));
console.log($("ul li"));
})
$(function() {
$("ul li:first").css("color", "red");
$("ul li:eq(2)").css("color", "blue");
$("ol li:odd").css("color", "skyblue");
$("ol li:even").css("color", "pink");
})
$('ul.lang li'); // 选出JavaScript、Python和Lua 3个节点
$('ul.lang li:first-child'); // 仅选出JavaScript
$('ul.lang li:last-child'); // 仅选出Lua
$('ul.lang li:nth-child(2)'); // 选出第N个元素,N从1开始
$('ul.lang li:nth-child(even)'); // 选出序号为偶数的元素
$('ul.lang li:nth-child(odd)'); // 选出序号为奇数的元素
存在,返回的jQuery对象[<div id="abc">...</div>]
不存在,返回的jQuery对象:[]
jQuery的选择器不会返回undefined或者null
var ps = $('p'); // 返回所有<p>节点
ps.length; // 数一数页面有多少个<p>节点
//按属性查找
比如在一个表单中按属性来查找:
var email = $('[name=email]'); // 找出<??? name="email">
var passwordInput = $('[type=password]'); // 找出<??? type="password">
var a = $('[items="A B"]'); // 找出<??? items="A B">
//当属性的值包含空格等特殊字符时,需要用双引号括起来。
//前缀查找或者后缀查找:
var icons = $('[name^=icon]'); // 找出所有name属性值以icon开头的DOM
// 例如: name="icon-1", name="icon-2"
var names = $('[name$=with]'); // 找出所有name属性值以with结尾的DOM
// 例如: name="startswith", name="endswith"
尤其适合通过class属性查找,且不受class包含多个名称的影响:
var icons = $('[class^="icon-"]'); // 找出所有class包含至少一个以`icon-`开头的DOM
// 例如: class="icon-clock", class="abc icon-home"
//组合查找
var emailInput = $('input[name=email]'); // 不会找出<div name="email">
var tr = $('tr.red'); // 找出<tr class="red ...">...</tr>
//表单相关
:input :可以选择<input>,<textarea>,<select>和<button>;
:file :可以选择<input type="file">,和input[type=file]一样;
:checkbox :可以选择复选框,和input[type=checkbox]一样;
:radio :可以选择单选框,和input[type=radio]一样;
:focus :可以选择当前输入焦点的元素
//例如把光标放到一个<input>上,用$('input:focus')就可以选出;
:checked :$('input[type=radio]:checked');
:enabled
:disabled :和:enabled正好相反,选择那些不能输入的。
//选出可见的或隐藏的元素:
$('div:visible'); // 所有可见的div
$('div:hidden'); // 所有隐藏的div
过滤
filter()方法可以过滤掉不符合选择器条件的节点:
var langs = $('ul.lang li'); // 拿到JavaScript, Python, Swift, Scheme和Haskell
var a = langs.filter('.dy'); // 拿到JavaScript, Python, Scheme
//或者传入一个函数
//要特别注意函数内部的this被绑定为DOM对象,不是jQuery对象:
var langs = $('ul.lang li'); // 拿到JavaScript, Python, Swift, Scheme和Haskell
langs.filter(function () {
return this.innerHTML.indexOf('S') === 0; // 返回S开头的节点
}); // 拿到Swift, Scheme
//一个jQuery对象如果包含了不止一个DOM节点,
//first()、last()和slice()方法可以返回一个新的jQuery对象,把不需要的DOM节点去掉:
var langs = $('ul.lang li'); // 拿到JavaScript, Python, Swift, Scheme和Haskell
var js = langs.first(); // JavaScript,相当于$('ul.lang li:first-child')
var haskell = langs.last(); // Haskell, 相当于$('ul.lang li:last-child')
var sub = langs.slice(2, 4); // Swift, Scheme, 参数和数组的slice()方法一致
操作DOM
一个jQuery对象可以包含0个或任意个DOM对象,它的方法实际上会作用在对应的每个DOM节点上
//1、修改Text、HTML
//jQuery对象的text()和html()方法分别获取节点的文本和原始HTML文本
$('#test-ul li[name=book]').text(); // 'Java & JavaScript'
$('#test-ul li[name=book]').html(); // 'Java & JavaScript'
//无参数调用text()是获取文本,传入参数就变成设置文本,HTML也是类似操作
// 如果不存在id为not-exist的节点:
$('#not-exist').text('Hello'); // 代码不报错,没有节点被设置为'Hello'
//2. index
$(this).index();//获取索引
//3. 表单的值val() 相当于原生value
val() //获取
val('content') //设置
substr(1) //截取字符串
toFixed(2)//保留两位小数
//遍历元素 2种语法 可用于遍历任何对象。
//jQuery 隐式迭代是对同一类元素做了同样的操作。
//如果想要给同一类元素做不同操作,就需要用到遍历。
$("div").each(function (index, domEle) { xxx; })
$.each(object,function (index, element) { xxx; })
//里面的回调函数有2个参数:
//index 是每个元素的索引号; demEle 是每个DOM元素对象,不是jquery对象
//创建元素
$('<li></li>')
//添加元素
//内部 内部添加元素,生成之后,它们是父子关系。
element.append('内容')
element.prepend('内容')//放最前面
//外部 外部添加元素,生成之后,他们是兄弟关系。
element.after('内容') // 把内容放入目标元素后面
element.before('内容') // 把内容放入目标元素前面
ul.append('<li><span>Haskell</span></li>');
// 添加jQuery对象:
ul.append($('#scheme'));
// 添加函数对象:
ul.append(function (index, html) {
return '<li><span>Language - ' + index + '</span></li>';
});
//如果要添加的DOM节点已经存在于HTML文档中,
//它会首先从文档移除,然后再添加
//如果要把新节点插入到指定位置,
//例如,JavaScript和Python之间,先定位到JavaScript,然后用after()
var js = $('#test-div>ul>li:first-child');
js.after('<li><span>Lua</span></li>');
//同级节点可以用after()或者before()方法。
//删除元素
element.remove() // 删除匹配的元素(本身)
element.empty() // 删除匹配的元素集合中所有的子节点
element.html('') // 清空匹配的元素内容
//如果jQuery对象包含若干DOM节点,实际上可以一次删除多个DOM节点:
var li = $('#test-div>ul>li');
li.remove(); // 所有<li>全被删除
- this指向
$(this) 代表的是当前正在执行事件处理函数时的 DOM 元素。this 指向的是触发事件的具体 DOM 元素,而通过 $(this) 包装后,可以调用 jQuery 提供的各种方法。 - 修改CSS
Query对象有“批量操作”的特点,这用于修改CSS实在是太方便了
// 注意:css() 多用于样式少时操作,多了则不太方便。
var div = $('#test-div');
div.css('color'); // '#000033', 获取CSS属性
div.css('color', '#336699'); // 设置CSS属性
div.css('color', ''); // 清除CSS属性
//参数可以是对象形式,方便设置多组样式。
//属性名和属性值用冒号隔开, 属性可以不用加引号
$(this).css({ "color":"white","font-size":"20px"});
//css()方法将作用于DOM节点的style属性,具有最高优先级。
//作用等同于以前classList操作类样式,注意操作类里面的参数不要加点。
//原生JS中className会覆盖元素原先里面的类名,jQuery 里面类操作只是对指定类进行操作,不影响原先的类名。
//如果要修改class属性,可以用
var div = $('#test-div');
div.hasClass('highlight'); // false, class是否包含highlight
div.addClass('highlight'); // 添加highlight这个class
div.removeClass('highlight'); // 删除highlight这个class
div.toggleClass("current");//切换类
//排他思想
// 想要多选一的效果,排他思想:当前元素设置样式,其余的兄弟元素清除样式。
$(this).css('color','red');
$(this).siblings(). css('color','');
//隐式迭代
// 遍历内部 DOM 元素(伪数组形式存储)的过程就叫做隐式迭代。
// 不用我们再进行循环,简化我们的操作,方便我们调用。
$('div').hide(); // 页面中所有的div全部隐藏,不用循环操作
// 链式编程是为了节省代码量,看起来更优雅。
$(this).css('color', 'red').siblings().css('color', '');
//让下部里面相应索引号的item显示,其余的item隐藏
$(".tab_con .item").eq(index).show().siblings().hide();
- 获取DOM信息
- 设置或获取元素固有属性值 prop()
是元素本身自带的属性 - 设置或获取元素自定义属性值 attr()
用户自己给元素添加的属性。 比如给 div 添加 index =“1”。 - 数据缓存
data() 方法可以在指定的元素上存取数据,并不会修改 DOM 元素结构。一旦页面刷新,之前存放的数据都将被移除。
prop('属性')
prop('属性', '属性值')
attr('属性') // 类似原生 getAttribute()
attr('属性', '属性值') // 类似原生 setAttribute()
div.attr('name'); // undefined
div.removeAttr('name'); // 删除name属性
data('name','value') // 向被选元素附加数据
date('name') // 向被选元素获取数据
//还可以读取 HTML5 自定义属性 data-index ,得到的是数字型
attr()和prop()对于属性checked处理有所不同:
var radio = $('#test-radio');
radio.attr('checked'); // 'checked'
radio.prop('checked'); // true
用is()方法判断更好:
var radio = $('#test-radio');
radio.is(':checked'); // true
类似的属性还有selected,处理时最好用is(':selected')
// 浏览器可视窗口大小:
$(window).width(); // 800
$(window).height(); // 600
// HTML文档大小:
$(document).width(); // 800
$(document).height(); // 3500
// 某个div的大小:
var div = $('#test-div');
div.width(); // 600
div.height(); // 300
div.width(400); // 设置CSS属性 width: 400px,是否生效要看CSS是否有效
div.height('200px'); // 设置CSS属性 height: 200px,是否生效要看CSS是否有效
css(‘height’)获取的是字符串带有单位,height() 获取的是数值,无单位。
- 位置信息
位置主要有三个: offset()、position()、scrollTop()/scrollLeft()
- offset() 设置或获取元素偏移
① offset() 方法设置或返回被选元素相对于文档的偏移坐标,跟父级没有关系。
② 该方法有2个属性 left、top 。offset().top 用于获取距离文档顶部的距离,offset().left 用于获取距离文档左侧的距离。
③ 可以设置元素的偏移:offset({ top: 10, left: 30 }); - position() 获取元素偏移
① position() 方法用于返回被选元素相对于带有定位的父级偏移坐标,如果父级都没有定位,则以文档为准。
② 该方法有2个属性 left、top。position().top 用于获取距离定位父级顶部的距离,position().left 用于获取距离定
位父级左侧的距离。
③ 该方法只能获取。 - scrollTop()/scrollLeft() 设置或获取元素被卷去的头部和左侧
① scrollTop() 方法设置或返回被选元素被卷去的头部。
② 不跟参数是获取,参数为不带单位的数字则是设置被卷去的头部。
拷贝对象
两套快速获取和设置元素尺寸和位置的API
//合并数据
var targetObj = {};
var obj = {
id: 1,
name: "andy"
};
// $.extend(target, obj);
$.extend(targetObj, obj);
console.log(targetObj);
事件
用jQuery来写代码,就屏蔽了不同浏览器的差异
- 优点: 操作简单,且不用担心事件覆盖等问题。
- 缺点: 普通的事件注册不能做事件委托,且无法实现事件解绑,需要借助其他方法。
事件回调函数中的 this 仍然指向的是添加事件监听的原生 DOM
- on(): 用于事件绑定,目前最好用的事件绑定方法
最后参数fn:回调函数
$(function() {
// (1) on可以绑定1个或者多个事件处理程序
// $("div").on({
// mouseenter: function() {
// $(this).css("background", "skyblue");
// },
// click: function() {
// $(this).css("background", "purple");
// }
// });
// 事件绑定
$("div").on({
click: function() {
console.log("我点击了");
},
mouseover: function() {
console.log('我鼠标经过了');
}
});
$("div").on("mouseenter mouseleave", function() {
$(this).toggleClass("current");
});
// (2) on可以实现事件委托(委派)
// click 是绑定在ul 身上的,但是 触发的对象是 ul 里面的小li
// $("ul li").click();
$("ul").on("click", "li", function() {
alert(11);
});
// (3) on可以给未来动态创建的元素绑定事件
$("ol").on("click", "li", function() {
alert(11);
})
var li = $("<li>我是后来创建的</li>");
$("ol").append(li);
})
- off(): 事件解绑
- trigger() / triggerHandler(): 事件触发
利用定时器自动触发右侧按钮点击事件,不必鼠标点击触发。
$('p').on('click',function(){
alert('hi');
})
$('p').trigger('click');//自动触发事件,无需鼠标点击
// 自动触发事件
// 1. 元素.事件()
// $("div").click();会触发元素的默认行为
// 2. 元素.trigger("事件")
// $("div").trigger("click");会触发元素的默认行为
$("input").trigger("focus");
// 3. 元素.triggerHandler("事件") 就是不会触发元素的默认行为
$("input").on("focus", function() {
$(this).val("你好吗");
});
// 一个会获取焦点,一个不会
$("div").triggerHandler("click");
// $("input").triggerHandler("focus");
// 获取超链接的jQuery对象:
var a = $('#test-link');
a.on('click', function () {
alert('Hello!');
});
//on方法用来绑定一个事件,我们需要传入事件名称和对应的处理函数。
//通常用后面的写法。更简化
a.click(function () {
alert('Hello!');
});
/*
$(function() {}) 是 jQuery 中的一个简写,用来在 DOM 加载完成后执行某段代码。
相当于 $(document).ready(function() {...}),
用于确保在 HTML 文档加载并且 DOM 树构建完成后,再执行你的 JavaScript 代码。
*/
$(function() {
// 鼠标经过
// $(".nav>li").mouseover(function() {
// // $(this) jQuery 当前元素 this不要加引号
// // show() 显示元素 hide() 隐藏元素
// $(this).children("ul").slideDown(200);
// });
// // 鼠标离开
// $(".nav>li").mouseout(function() {
// $(this).children("ul").slideUp(200);
// });
// 1. 事件切换 hover 就是鼠标经过和离开的复合写法
// $(".nav>li").hover(function() {
// $(this).children("ul").slideDown(200);
// }, function() {
// $(this).children("ul").slideUp(200);
// });
// 2. 事件切换 hover 如果只写一个函数,那么鼠标经过和鼠标离开都会触发这个函数
$(".nav>li").hover(function() {
// stop 方法必须写到动画的前面
$(this).children("ul").stop().slideToggle();
});
})
鼠标事件
click: 鼠标单击时触发;
dblclick:鼠标双击时触发;
mouseenter:鼠标进入时触发;
mouseleave:鼠标移出时触发;
mousemove:鼠标在DOM内部移动时触发;
hover:鼠标进入和退出时触发两个函数,相当于mouseenter加上mouseleave。
hover([over,]out) // 其中over和out为两个函数
over:鼠标移到元素上要触发的函数(相当于mouseenter)
out:鼠标移出元素要触发的函数(相当于mouseleave)
如果只写一个函数,则鼠标经过和离开都会触发它
键盘事件
键盘事件仅作用在当前焦点的DOM上,通常是< input>和< textarea>。
keydown:键盘按下时触发;
keyup:键盘松开时触发;
keypress:按一次键后触发。
其他事件
focus:当DOM获得焦点时触发;
blur:当DOM失去焦点时触发;
change:当< input>、< select>或< textarea>的内容改变时触发;
submit:当< form>提交时触发;
ready:当页面被载入并且DOM树完成初始化后触发。
其中,ready仅作用于document对象。由于ready事件在DOM完成初始化后触发,且只触发一次,所以非常适合用来写其他的初始化代码。
$(function() {})
是 jQuery 中的一个简写,用来在 DOM 加载完成后执行某段代码。它相当于 $(document).ready(function() {...})
,用于确保在 HTML 文档加载并且 DOM 树构建完成后,再执行你的 JavaScript 代码。
效果
显示隐藏:show() / hide() / toggle() ;
这三种都包含同样参数:
划入画出:slideDown()下滑动 / slideUp() 上滑动/ slideToggle() 滑动切换; 同理参数
淡入淡出:fadeIn() / fadeOut() / fadeToggle() / fadeTo()调整不透明度 ; 前三个参数还是一样
自定义动画:animate() ;可以模拟显示隐藏、滑入滑出、淡入淡出等动画,使用原则为哪个方便用哪个。jQuery中的animate()不能实现背景色渐变,需要引入插件
jQuery不能对 background-color 进行动画效果 ,在 animate()设置background-color也没有效果。可以使用CSS3的transition实现动画效果
停止动画排队:stop() ;
每次使用动画之前,先调用 stop() 停止结束上一次的动画,在调用动画。
注意:动画或者效果一旦触发就会执行,如果多次触发,就造成多个动画或者效果排队执行。停止动画排队:stop() ;
暂停:delay()
为什么有的动画没效果?
1)属性不是block 设置Height不起作用
2)jQuery不能对 background-color 进行动画效果 ,在 animate()设置background-color也没有效果。可以使用CSS3的transition实现动画效果
$(function() {
$("button").click(function() {
$("div").animate({
left: 500,
top: 300,
opacity: .4,
width: 500
}, 500);
})
})
//只要传递一个时间参数进去,就变成了动画:
var div = $('#test-show-hide'); // # id
div.hide(3000); // 在3秒钟内逐渐消失
div.show('slow'); // 在0.6秒钟内逐渐显示
//toggle()方法则根据当前状态决定是show()还是hide()
//show()和hide()是从左上角逐渐展开或收缩的,
//而slideUp()/slideDown()/slideToggle()则是在垂直方向逐渐展开或收缩的。
3、 fadeIn / fadeOut
fadeIn()和fadeOut()的动画效果是淡入淡出,也就是通过不断设置DOM元素的opacity属性来实现,而fadeToggle()则根据元素是否可见来决定下一步动作:
var div = $('#test-fade');
div.fadeOut('slow'); // 在0.6秒内淡出
var div = $('#test-animate');
div.animate({
opacity: 0.25,
width: '256px',
height: '256px'
}, 3000, function () {
console.log('动画已结束');
// 恢复至初始状态:
$(this).css('opacity', '1.0').css('width', '128px').css('height', '128px');
});
delay()方法 实现暂停
// 动画效果:slideDown - 暂停 - 放大 - 暂停 - 缩小
div.slideDown(2000)
.delay(1000)
.animate({
width: '256px',
height: '256px'
}, 2000)
.delay(1000)
.animate({
width: '128px',
height: '128px'
}, 2000);
// 因为动画需要执行一段时间,
//所以jQuery必须不断返回新的Promise对象才能后续执行操作。简单地把动画封装在函数中是不够的。
jQuery中的JSONP
jQuery 提供的 $.ajax() 函数,除了可以发起真正的 Ajax 数据请求之外,还能够发起 JSONP 数据请求。默认情况下,使用 jQuery 发起 JSONP 请求,会自动携带一个 callback=jQueryxxx 的参数,jQueryxxx 是随机生成的一个回调函数名称。
jQuery 中的 JSONP,也是通过 < script> 标签的 src 属性实现跨域数据访问的,只不过,jQuery 采用的是动态创建和移除 < script> 标签的方式,来发起 JSONP 数据请求。
在发起 JSONP 请求的时候,动态向 < header> 中 append 一个 < script> 标签;
在 JSONP 请求成功以后,动态从 < header> 中移除刚才 append 进去的 < script> 标签;
- jquery自动会加上回调函数名(或者自定义名称),告诉后端:“后端你别直接返回数据,你要调用我叫 “回调函数名”的函数,把数据当参数传给我。”这是 JSONP 的核心机制。
如果你用的是现代前端(比如 fetch 或 axios),那就不用 JSONP 了,因为现在可以用 CORS 跨域请求。但在一些老旧系统里 JSONP 还挺常见。
$.ajax({
url: 'http://ajax.frontend.net:3006/api/jsonp?name=zs&age=20',
// 如果要使用 $.ajax() 发起 JSONP 请求,必须指定 datatype 为 jsonp
dataType: 'jsonp',
success: function(res) {
console.log(res)
}
})
//自定义参数及回调函数名称
//使用 jQuery 发起 JSONP 请求时,
//如果想要自定义 JSONP 的参数以及回调函数名称,可以通过如下两个参数来指定:
$.ajax({
url: 'http://ajax.frontend.net:3006/api/jsonp?name=zs&age=20',
dataType: 'jsonp',
// 发送到服务端的参数名称,默认值为 callback
jsonp: 'callback',
// 自定义的回调函数名称,默认值为 jQueryxxx 格式
jsonpCallback: 'abc',
success: function(res) {
console.log(res)
}
})
AJAX
jQuery对AJAX进行封装,简化使用,并且不需要考虑浏览器问题
jQuery在全局对象jQuery(也就是$)绑定了ajax()函数,可以处理AJAX请求
- 注意
在 jQuery 的 $.get 和 $.post 请求中,默认是会带上当前页面域名下的 cookie 的,只要满足以下条件:
✅ 带上 cookie 的前提条件
请求是同源的(Same Origin)
没有被设置为跨域并且不手动禁用 cookie
🚨 如果是跨域请求(比如从 example.com 请求 api.example.com):
你就需要用 $.ajax 并加上 xhrFields: { withCredentials: true },而且服务器也要允许带 cookie。
$.get(url,[data],[callback])
$.post(url,[data],[callback])
$.ajax({
type:'',//get or post
url:'',
data:{},
success:function(res){}
})
/*
contentType:发送POST请求的格式,
默认值为'application/x-www-form-urlencoded; 也可以指定为text/plain、application/json;
charset=UTF-8',
data:发送的数据,可以是字符串、数组或object。
如果是GET请求,data将被转换成query附加到URL上,
如果是POST请求,根据contentType把data序列化成合适的格式;
headers:发送的额外的HTTP头,必须是一个object
dataType:返回、接收的数据格式,可以指定为'html'、'xml'、'json'、'text'等,缺省情况下根据响应的Content-Type猜测。
*/
$.ajax({
url: 'https://api.example.com/user',
method: 'GET',
xhrFields: {
withCredentials: true // 关键点!允许发送cookie
},
crossDomain: true, // 显式告诉 jQuery 这是跨域请求
success: function(data) {
console.log(data);
},
error: function(err) {
console.error('失败', err);
}
});
$.ajax({
url: 'https://api.example.com/login',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({ username: 'test', password: '123456' }),
xhrFields: {
withCredentials: true
},
crossDomain: true,
success: function(res) {
console.log('登录成功', res);
},
error: function(err) {
console.error('登录失败', err);
}
});
const base_prefix='http://localhost:5500'
$(function () {
// 监听表单的提交事件
$('#form1').on('submit', function (e) {
// 阻止默认提交行为
e.preventDefault()
// 发起 POST 登录请求
$.ajax({
url:`${base_prefix}/api/login`,
type:'POST',
contentType: 'application/json',
data:$(this).serialize(),
xhrFields: {
withCredentials: true
},
crossDomain:true,
success:function (res) {
console.log(res)
// status 为 0 表示登录成功;否则表示登录失败!
if (res.status === 0) {
location.href = './index.html'
} else {
alert('登录失败!')
}
}
})
})
})
$.ajax({
url: '/api/user', // 你的接口地址
type: 'GET', // 请求方法
data: { id: 123 }, // 查询参数,会自动拼接为 ?id=123
success: function(res) {
console.log('请求成功:', res);
},
error: function(xhr, status, err) {
console.error('请求失败:', err);
}
});
$.ajax({
url: '/api/user',
type: 'GET',
data: { id: 123 },
headers: {
'Authorization': 'Bearer your_token_here'
},
success: function(res) {
console.log('成功:', res);
}
});
$.get('url',{id:1},function(res){
console.log(res);
})
$.post('url',
{id:1,name:'abc'},
function(res){
console.log(res);
})
//为发送按钮绑定点击事件处理函数
$('#btnSend').on('click', function0 {
var text= $('#ipt').val().trim() // 获取用户输入的肉容
if(text.length <=0){// 判断用户输入的内容是否为空
return $('#ipt').val('')
}
//将用户输入的内容显示到聊天窗口中
$('#talk_list').append('<li class="right_word"><img src='img/persono2.png' /><span>' + text +'</span></li>')
resetui() //重置滚动条的位置
$('#ipt').val('') // 清空输入框的内容
//TODO:发起请求,获取聊天消息
})
//$('#voice').attr('src', res.voiceUrl)
//让文本输入框响应回车事件后,提交消息
$('#ipt').on('keyup', function (e) {//e.keyCode 可获取到当前按键的编码
if(e.keycode ==13){
//调用按钮元素的 click 函数,可以通过编程的形式触发按钮的点击事件
$('#btnSend').click()
}
})
function getCmtList() {
$.get('http://test.top:3006/api/cmtlist', function (res) {
if(res.status !== 200) {
return alert('获取评论列表失败!')
}
var rows = []
$.each(res.data, function (i, item) { // 循环拼接字符串
rows.push('<li class="list-group-item">'+ item.content +'<span class="badge cmt-date">评论时间:'+ item.time +'</span><span class="badge cmt-person">评论人:'+ item.username +'</span></li>')
})
$('#cmt-list').empty().append(rows.join('')) // 渲染列表的UI结构
})
}
//如何用回调函数处理返回的数据和出错时的响应呢
//jQuery的jqXHR对象类似一个Promise对象,用链式写法来处理各种回调:
格式:
var jqxhr = $.ajax('/api/categories', {
dataType: 'json'
}).done(function (data) {
ajaxLog('成功, 收到的数据: ' + JSON.stringify(data));
}).fail(function (xhr, status) {
ajaxLog('失败: ' + xhr.status + ', 原因: ' + status);
}).always(function () {
ajaxLog('请求完成: 无论成功或失败都会调用');
});
getJSON()方法来快速通过GET获取一个JSON对象
var jqxhr = $.getJSON('/path/to/resource', {
name: 'Bob Lee',
check: 1
}).done(function (data) {
// data已经被解析为JSON对象了
});
jQuery的AJAX完全封装的是JavaScript的AJAX操作,所以它的安全限制和前面讲的用JavaScript写AJAX完全一样。
需要使用JSONP,可以在ajax()中设置jsonp: 'callback',让jQuery实现JSONP跨域加载数据
跨域的安全限制都是对浏览器端来说的,服务器端是不存在跨域安全限制的。
在页面上直接发起一个跨域的ajax请求是不可以的,
但是一般在页面上引入不同域上的js脚本却是可以的。
jquery的jsonp方式跨域请求 这一块详见https://www.cnblogs.com/chiangchou/p/jsonp.html
表单
- 监听表单提交事件
$('#form1').submit(function(e) {
alert('监听到了表单的提交事件')
})
$('#form1').on('submit', function(e) {
alert('监听到了表单的提交事件')
})
- 阻止表单默认提交行为
$('#form1').submit(function(e) {
// 阻止表单的提交和页面的跳转
e.preventDefault()
})
$('#form1').on('submit', function(e) {
// 阻止表单的提交和页面的跳转
e.preventDefault()
})
- 快速获取表单数据
$(selector).serialize() //一次性获取到表单所有数据
// 调用的结果:
// username=用户名的值&password=密码的值
//注意:使用 serialize()函数快速获取表单数据时,必须为每个表单元素添加 name 属性!
$('#formAddCmt').submit(function(e) {
e.preventDefault() // 阻止表单的默认提交行为
// 快速得到表单中的数据
var data = $(this).serialize()
$.post('http://test.top:3006/api/addcmt', data, function(res) {
if (res.status !== 201) {
return alert('发表评论失败!')
}
// 刷新评论列表
getCmtList()
// 快速清空表单内容
$('#formAddCmt')[0].reset()
})
})
模版引擎
上面和下面代码中常出现渲染UI结构时候的一大串字符串拼接的html串,如果UI结构比较复杂,结构不清晰,维护和阅读都非常麻烦。
模版引擎:根据程序员指定的模版结构和数据,自动生成完整的html页面。
数据+模版结构->模版引擎->html页面
- art-template模版引擎 点击进入官网
- 使用方法:将 art-template 下载到本地,然后,通过 < script> 标签加载到网页上进行使用。导入art-template->定义数据+模版->调用template函数->渲染html结构
//标准语法{{}}可以进行变量输出、循环数组等操作
{{obj.key}}
{{obj[key]}}
{{a?b:c}}
{{a||b||a+b}}//里面可以放表达式
//原文输出 value是包含html解构的文本
{{@ value}}
//条件输出
{{if value}}content{{/if}}
{{if v1}}content {{else if v2}}other_content{{/if}}
//循环输出
//实现循环输出,则可以在 {{ }} 内,通过 each 语法循环数组,
//当前循环的索引使用 $index 进行访问,当前的循环项使用 $value 进行访问。
{{each arr}}
{{$index}} {{$value}}
{{/each}}
//过滤器 本质function函数
//定义过滤器
template.defaults.imports.filterName = function(value){
/*return处理的结果*/}
{{value | filterName}}//过滤器语法类似管道操作符,它的上一个输出作为下一个输入。
template.defaults.imports.dateFormat = function(date) {
var y = date.getFullYear()
var m = date.getMonth() + 1
var d = date.getDate()
return y + '-' + m + '-' + d // 注意,过滤器最后一定要 return 一个值
}
<div>注册时间:{{regTime | dateFormat}}</div>
//栗子
<!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>Document</title>
<!-- 1. 导入模板引擎 -->
<!-- 在 window 全局,多一个函数,叫做 template('模板的Id', 需要渲染的数据对象) -->
<script src="./lib/template-web.js"></script>
<script src="./lib/jquery.js"></script>
</head>
<body>
<div id="container"></div>
<!-- 3. 定义模板 -->
<!-- 3.1 模板的 HTML 结构,必须定义到 script 中 -->
<script type="text/html" id="tpl-user">
<h1>{{name}} ------ {{age}}</h1>
{{@ test}}
<div>
{{if flag === 0}}
flag的值是0
{{else if flag === 1}}
flag的值是1
{{/if}}
</div>
<ul>
{{each hobby}}
<li>索引是:{{$index}},循环项是:{{$value}}</li>
{{/each}}
</ul>
<h3>{{regTime | dateFormat}}</h3>
</script>
<script>
// 定义处理时间的过滤器
template.defaults.imports.dateFormat = function (date) {
var y = date.getFullYear()
var m = date.getMonth() + 1
var d = date.getDate()
return y + '-' + m + '-' + d
}
// 2. 定义需要渲染的数据
var data = { name: 'zs', age: 20, test: '<h3>测试原文输出</h3>', flag: 1, hobby: ['吃饭', '睡觉', '写代码'], regTime: new Date() }
// 4. 调用 template 函数
var htmlStr = template('tpl-user', data)
console.log(htmlStr)
// 5. 渲染HTML结构
$('#container').html(htmlStr)
</script>
</body>
</html>
- 模版引擎实现原理:正则表达式
exec() 函数用于检索字符串中的正则表达式的匹配。如果字符串中有匹配的值,则返回该匹配值,否则返回 null。
var str = 'hello'
var pattern = /o/
// 输出的结果["o", index: 4, input: "hello", groups: undefined]
console.log(pattern.exec(str))
var str = '<div>我是{{name}}</div>'
var pattern = /{{([a-zA-Z]+)}}/
var patternResult = pattern.exec(str)
console.log(patternResult)
// 得到 name 相关的分组信息
// ["{{name}}", "name", index: 7, input: "<div>我是{{name}}</div>", groups: undefined]
/*
如果 exec() 匹配到了内容,它返回一个 数组,包含:
match[0]:整个匹配到的字符串(完整的 {{name}})。
match[1]:第一个捕获组 ([a-zA-Z]+) 的内容,即 "name"。
index:匹配在 str 中的起始位置(这里是索引 5)。
input:原始字符串 str。
groups:如果使用 命名捕获组,会存储匹配的组(在这个例子里是 undefined)。
*/
var str = '<div>{{name}}今年{{ age }}岁了</div>'
var pattern = /{{\s*([a-zA-Z]+)\s*}}/
var patternResult = pattern.exec(str)
str = str.replace(patternResult[0], patternResult[1])
console.log(str) // 输出 <div>name今年{{ age }}岁了</div>
patternResult = pattern.exec(str)
str = str.replace(patternResult[0], patternResult[1])
console.log(str) // 输出 <div>name今年age岁了</div>
patternResult = pattern.exec(str)
console.log(patternResult) // 输出 null
var str = '<div>{{name}}今年{{ age }}岁了</div>'
var pattern = /{{\s*([a-zA-Z]+)\s*}}/
var patternResult = null
while(patternResult = pattern.exec(str)) {
str = str.replace(patternResult[0], patternResult[1])
}
console.log(str) // 输出 <div>name今年age岁了</div>
var data = { name: '张三', age: 20 }
var str = '<div>{{name}}今年{{ age }}岁了</div>'
var pattern = /{{\s*([a-zA-Z]+)\s*}}/
var patternResult = null
while ((patternResult = pattern.exec(str))) {
str = str.replace(patternResult[0], data[patternResult[1]])
}
console.log(str)
- 实现简单的模版引擎
定义模板结构
预调用模板引擎
封装 template 函数
导入并使用自定义的模板引擎
<!-- 定义模板结构 -->
<script type="text/html" id="tpl-user">
<div>姓名:{{name}}</div>
<div>年龄:{{ age }}</div>
<div>性别:{{ gender}}</div>
<div>住址:{{address }}</div>
</script>
<script>
//预调用模版引擎
// 定义数据
var data = { name: 'zs', age: 28, gender: '男', address: '北京顺义马坡' }
// 调用模板函数
var htmlStr = template('tpl-user', data)
// 渲染HTML结构
document.getElementById('user-box').innerHTML = htmlStr
//封装template函数
function template(id, data) {
var str = document.getElementById(id).innerHTML
var pattern = /{{\s*([a-zA-Z]+)\s*}}/
var pattResult = null
while ((pattResult = pattern.exec(str))) {
str = str.replace(pattResult[0], data[pattResult[1]])
}
return str
}
</script>
//导入并使用自定义模版引擎
<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>
<!-- 导入自定义的模板引擎 -->
<script src="./js/template.js"></script>
</head>
实例:图书管理
<!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>Document</title>
<link rel="stylesheet" href="./lib/bootstrap.css" />
<script src="./lib/jquery.js"></script>
</head>
<body style="padding: 15px;">
<!-- 添加图书的Panel面板 -->
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">添加新图书</h3>
</div>
<div class="panel-body form-inline">
<div class="input-group">
<div class="input-group-addon">书名</div>
<input type="text" class="form-control" id="iptBookname" placeholder="请输入书名">
</div>
<div class="input-group">
<div class="input-group-addon">作者</div>
<input type="text" class="form-control" id="iptAuthor" placeholder="请输入作者">
</div>
<div class="input-group">
<div class="input-group-addon">出版社</div>
<input type="text" class="form-control" id="iptPublisher" placeholder="请输入出版社">
</div>
<button id="btnAdd" class="btn btn-primary">添加</button>
</div>
</div>
<!-- 图书的表格 -->
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>Id</th>
<th>书名</th>
<th>作者</th>
<th>出版社</th>
<th>操作</th>
</tr>
</thead>
<tbody id="tb"></tbody>
</table>
<script>
$(function () {
// 获取图书列表数据
function getBookList() {
$.get('http://test.top:3006/api/getbooks', function (res) {
if (res.status !== 200) return alert('获取数据失败!')
var rows = []
$.each(res.data, function (i, item) {
rows.push('<tr><td>' + item.id + '</td><td>' + item.bookname + '</td><td>' + item.author + '</td><td>' + item.publisher + '</td><td><a href="javascript:;" class="del" data-id="' + item.id + '">删除</a></td></tr>')
})
$('#tb').empty().append(rows.join(''))
})
}
getBookList()
/* $('.del').on('click', function () {
console.log('ok')
}) */
// 通过代理的方式为动态添加的元素绑定点击事件
$('tbody').on('click', '.del', function () {
var id = $(this).attr('data-id')
$.get('http://test.top:3006/api/delbook', { id: id }, function (res) {
if (res.status !== 200) return alert('删除图书失败!')
getBookList()
})
})
$('#btnAdd').on('click', function () {
var bookname = $('#iptBookname').val().trim()
var author = $('#iptAuthor').val().trim()
var publisher = $('#iptPublisher').val().trim()
if (bookname.length <= 0 || author.length <= 0 || publisher.length <= 0) {
return alert('请填写完整的图书信息!')
}
$.post('http://test.top:3006/api/addbook', { bookname: bookname, author: author, publisher: publisher }, function (res) {
if (res.status !== 201) return alert('添加图书失败!')
getBookList()
$('#iptBookname').val('')
$('#iptAuthor').val('')
$('#iptPublisher').val('')
})
})
})
</script>
</body>
</html>
文件上传
<!-- 导入 jQuery -->
<script src="./lib/jquery.js"></script>
<!-- 文件选择框 -->
<input type="file" id="file1" />
<!-- 上传文件按钮 -->
<button id="btnUpload">上传</button>
$('#btnUpload').on('click', function() {
// 1. 将 jQuery 对象转化为 DOM 对象,并获取选中的文件列表
var files = $('#file1')[0].files
// 2. 判断是否选择了文件
if (files.length <= 0) {
return alert('请选择图片后再上传!‘)
}
})
// 向 FormData 中追加文件
var fd = new FormData()
fd.append('avatar', files[0])
$.ajax({
method: 'POST',
url: 'http://test.top:3006/api/upload/avatar',
data: fd,
// 不修改 Content-Type 属性,使用 FormData 默认的 Content-Type 值
contentType: false,
// 不对 FormData 中的数据进行 url 编码,而是将 FormData 数据原样发送到服务器
processData: false,
success: function(res) {
console.log(res)
}
})
- jQuery实现loading效果
- ajaxStart(callback)
Ajax 请求开始时,执行 ajaxStart 函数。可以在 ajaxStart 的 callback 中显示 loading 效果
注意: $(document).ajaxStart() 函数会监听当前文档内所有的 Ajax 请求。
// 自 jQuery 版本 1.8 起,该方法只能被附加到文档
$(document).ajaxStart(function() {
$('#loading').show()
})
- ajaxStop(callback)
Ajax 请求结束时,执行 ajaxStop 函数。可以在 ajaxStop 的 callback 中隐藏 loading 效果
// 自 jQuery 版本 1.8 起,该方法只能被附加到文档
$(document).ajaxStop(function() {
$('#loading').hide()
})
编写jQuery插件
高亮显示某些DOM元素,用jQuery可以这么实现:
$('span.hl').css('backgroundColor', '#fffceb').css('color', '#d85030');
$('p a.hl').css('backgroundColor', '#fffceb').css('color', '#d85030');
能不能统一起来,写个highlight()方法
$('span.hl').highlight();
$('p a.hl').highlight();
可以编写jQuery插件,扩展jQuery来实现自定义方法
给jQuery对象绑定一个新方法是通过扩展$.fn对象实现的
$.fn.highlight1 = function () {
// this已绑定为当前jQuery对象:
this.css('backgroundColor', '#fffceb').css('color', '#d85030');
return this;
}
注意到函数内部的this在调用时被绑定为jQuery对象,所以函数内部代码可以正常调用所有jQuery对象的方法。
为什么最后要return this;?因为jQuery对象支持链式操作,我们自己写的扩展方法也要能继续链式下去:
即:还可以
$('span.hl').highlight1().slideDown();
我们可以给方法加个参数,让用户自己把参数用对象传进去。于是
$.fn.highlight2 = function (options) {
// 要考虑到各种情况:
// options为undefined
// options只有部分key
var bgcolor = options && options.backgroundColor || '#fffceb';
var color = options && options.color || '#d85030';
this.css('backgroundColor', bgcolor).css('color', color);
return this;
}
另一种方法是使用jQuery提供的辅助方法$.extend(target, obj1, obj2, ...),它把多个object对象的属性合并到第一个target对象中,遇到同名属性,总是使用靠后的对象的值,也就是越往后优先级越高
// 把默认值和用户传入的options合并到对象{}中并返回:
var opts = $.extend({}, {
backgroundColor: '#00a8e6',
color: '#ffffff'
}, options);//优先使用用户自定义的option
每次调用都需要传入自定义的设置,能不能让我自己设定一个缺省值,以后的调用统一使用无参数的highlight2()?我们设定的默认值应该能允许用户修改。
那默认值放哪比较合适?放全局变量肯定不合适,最佳地点是$.fn.highlight2这个函数对象本身
$.fn.highlight = function (options) {
// 合并默认值和用户设定值:
var opts = $.extend({}, $.fn.highlight.defaults, options);
this.css('backgroundColor', opts.backgroundColor).css('color', opts.color);
return this;
}
// 设定默认值:
$.fn.highlight.defaults = {
color: '#d85030',
backgroundColor: '#fff8de'
}
用户使用时,只需一次性设定默认值:
$.fn.highlight.defaults.color = '#fff';
$.fn.highlight.defaults.backgroundColor = '#000';
编写一个jQuery插件的原则:
给$.fn绑定函数,实现插件的代码逻辑;
插件函数最后要return this;以支持链式调用;
插件函数要有默认值,绑定在$.fn.<pluginName>.defaults上;
用户在调用时可传入设定值以便覆盖默认值。
我们知道jQuery对象的有些方法只能作用在特定DOM元素上,比如submit()方法只能针对form。如果我们编写的扩展只能针对某些类型的DOM元素,应该怎么写?
还记得jQuery的选择器支持filter()方法来过滤吗?我们可以借助这个方法来实现针对特定元素的扩展。
举个例子,现在我们要给所有指向外链的超链接加上跳转提示,怎么做?
先写出用户调用的代码:
$('#main a').external();
编写一个external扩展:
$.fn.external = function () {
// return返回的each()返回结果,支持链式调用:
return this.filter('a').each(function () {
// 注意: each()内部的回调函数的this绑定为DOM本身!
var a = $(this);
var url = a.attr('href');
if (url && (url.indexOf('http://')===0 || url.indexOf('https://')===0)) {
a.attr('href', '#0')
.removeAttr('target')
.append(' <i class="uk-icon-external-link"></i>')
.click(function () {
if(confirm('你确定要前往' + url + '?')) {
window.open(url);
}
});
}
});
}