目录
一、介绍
jQuery是javascript的一个库,主要用于简化的DOM树的操作,屏蔽各浏览器之间的差异。这里只介绍了jQuery的核心知识、DOM树的操作和ajax。还提了下事件,还有特效(effect)和ui控件的内容没有提及,但是可以参考最下方的链接教程。
二、核心知识
jQuery库的所有内容都被包含在jQuery
名字空间中,而$
默认为jQuery
的匿名。通过方法jQuery()
,即$()
可以生产一个jQuery对象,几乎所有的DOM操作都是对jQuery对象进行操作的。但是有些方法并不是jQuery对象的方法,而是$
的方法,都是一些有用的工具类方法。
可以这么理解:把$
当做类,$()
当做构造函数,生成的对象即为jQuery对象。。。实际上,jQuery对象的方法和属性源自于$.fn
通常API文档中.each()
这种形式的方法表示为jQuery对象的方法,而$.each()
表示$
的方法(理解成类方法。。)
一般jQuery的使用都是先从$()方法开始的,该方法可以通过css的选择器找到匹配的元素集合,存入新生成的jQuery对象中并返回jQuery对象;或者传入含html代码的字符串,通过该方法生成对应元素,但该元素还未放入DOM树中,同样的也是返回jQuery对象。
jQuery对象就像是元素集合的包装器一样,提供了更为方便的方法来操作DOM树的元素。可以像数组一样通过下标获取它的元素对象,使用元素对象的原生态方法,但是一般不会这样使用,因为jQuery对象提供的方法更方便。jQuery对象还拥有length属性,该属性表明匹配元素的个数。注意,jQuery即使像数组,但却不是数组。
jQuery的选择器包含了大部分css3选择器,用法和css一样。可以参考下面的链接,或我的博客:css。
参考:
selecting elements
selectors
2.1、引入jQuery
js在DOM树构建完成前执行是很不安全的,在我的js入门中介绍了一些解决方法。但在jquery中,也有它自己的办法。如:
$( document ).ready(function() {
//Your code here
});
//或者一种简写方式
$(function() {
// Your code here.
});
它表示为当文档DOM已经准备好了时(ready事件发生),执行匿名函数的内容。但是此时可能图片或iframes还未加载完成,因此如果需要整个网页都准备好时才执行代码,可以监听window的load事件:
$( window ).on( "load", function() {
//Your code here
});
如果引入多个库,其他库也用到了$
这个标识符,然后之后再引入jQuery则会造成名字冲突,覆盖了$
的内容。解决方法如下:
- 创建新匿名:
jQuery.noConflict()
方法可以放弃$
变量的控制,并返回jQuery。赋值给其他变量可以重新匿名,或者直接let jq2=jQuery
也行。<script src="prototype.js"></script> <script src="jquery.js"></script> <script> // Give $ back to prototype.js; create new alias to jQuery. var $jq = jQuery.noConflict(); </script>
- 设置ready事件的处理器参数名为
$
:处理器会自动被传入jQuery作为参数,因此可以使用$
作为参数。<script src="jquery.js"></script> <script src="prototype.js"></script> <script> //因为jquery位于其他库之前,没有产生名字冲突,因此不必使用$.noConflict() jQuery(function($){ // Your jQuery code here, using the $ }); </script>
2.2、操作DOM
jQuery对象提供了一些列操作DOM元素的方法。
参考:
Manipulation
Manipulating Elements
2.2.1、getting和setting
下面的一些方法都可以获得元素对应的信息,也可以设置元素的内容。当获得信息是,一般是获得元素集中第一个元素的信息,除了例外.text
(它将所有元素的文本拼接而成);当设置信息时,会分别对元素集中所有元素设置。
.html()
– Get or set the HTML contents..text()
– Get or set the text contents; HTML will be stripped..attr()
– Get or set the value of the provided attribute..prop()
--得到或设置元素内部property.width()
– Get or set the width in pixels of the first element in the selection as an integer..height()
– Get or set the height in pixels of the first element in the selection as an integer..position()
– Get an object with position information for the first element in the selection, relative to its first positioned ancestor. This is a getter only..val()
– Get or set the value of form elements.
jquery 1.6+后,
.attr()
方法不能再设置property了,所谓property就是元素内部的属性(或字段)。一些boolean attribute,如checked
可以初始化property,但之后不能改变它,因此使用.attr()
方法设置checkbox类型的input的选中状态已经没用了,只能使用.prop()
方法。参考:.prop
2.2.2、adding
下面的方法可以添加或者移动元素。
.append()
,.appendTo()
,.prepend()
,.prependTo()
分别可以将元素添加到元素内的前端或后端。
.after()
,.insertAfter()
,.before()
,.insertBefore()
分别可以将元素添加到元素的前面或后面。
一般移动DOM元素时,原来的元素位置会改变。如果我只想克隆该元素到其他地方呢?则可以使用.clone()
$( "#myList li:first" ).clone().appendTo( "#myList" );
通过$()
可以方便的创建新的元素,然后通过上面的方法将元素放入DOM树中。
2.2.3、removing
.remove()
,.detach()
都可以删除元素,然后返回对应jQuery对象。但是前者在删除元素后不会保存关联的数据和事件处理器,后者保存。.detach()
可以方便的恢复被删除的元素。
.empty()
可以删除元素内所有子元素(包括文字)。
2.2.4、attributes
.attr()
可以获得或者设置属性。
还有一些设置类属性的方法:class attrubte
2.2.5、styles
.css()
方法用于设置和获得样式。虽然支持样式名字含有“-”符号(js中不支持),最好使用驼峰命名法。
还有一些属性可以获得或者设置元素的尺寸,但提倡使用css获得它的长宽:
2.3、Traversing DOM
遍历元素的方法大致分为两类:
- 过滤以匹配的元素集合,如
.eq()
,.first()
,.last()
等等。 - 遍历DOM树的方法,可以遍历父元素、子元素和兄弟元素。
还有一些工具方法。只要知道这些方法大致分类就行了,使用时查查文档即可。
参考:Traversing
2.4、获得元素
通过$(selector)
可以得到jQuery对象,并且它提供的方法不仅跨浏览器还很方便,但是在某些特殊情况下还是需要操作元素对象时,可以通过.get()
方法或者下标[]
来获得元素对象(Element
)。
当想使用jQuery的方法时,可以将元素对象转化为jQuery对象:$(element)
三、事件
在官方文档中,有一章关于事件的内容,我没有怎么看,只是大致了解了下。jQuery只是提供更为方便的设置事件的方法,我怀疑event对象也被jQuery扩充了内容。但大致上来说,总的内容是不变的,可以参考我的另一篇博文。
任意事件处理器都可以通过.on()
方法来设置,jQuery也提供了更为方便的方法,如.click()
,,focus()
,.blur()
,.change()
等等,这些方法可以绑定事件处理器,同时也可以手动触发该事件。
event对象中多了个data属性,因此设置处理器时传入的额外数据可以在处理函数中获得。
一些有用的方法:
.on()
:对所有元素集附加事件处理器.off()
:去除事件处理器.one()
:所有元素都附加一个事件处理器,对于每种事件,事件处理器只执行一种。
所有的事件:https://developer.mozilla.org/en-US/docs/Web/Events
注意,事件处理函数(handler)中的this为被操作元素本身,而不是jquery对象
更多内容请参考官方文档。。。
四、Ajax
ajax可以让浏览器和服务器之间异步交换数据,而不是重新载入整个网页。
所谓异步即一个操作启动执行后,不用等待该操作完成,而是直接执行后续操作,当操作结束时会通知(即调用回调函数)。
尽管ajax全名Asynchronous JavaScript and XML,但是数据不仅可以以xml方式传输,还可以以json、text、html等等方式传输。其中json最为常用。
通常,由于浏览器的同源政策(same origin policy),ajax是不能跨域名工作的。但是,JSONP利用<script>
标签可以从其他域名的网站上获得json数据。
jQuery最底层的$.ajax()
方法提供了执行异步http请求的功能。也提供了简化一点的ajax方法,如$.get()
,$.post()
,$.getJSON()
,$.load()
等方法,这只不过是对$.ajax()
的简单封装罢了。因此,最主要的还是了解$.ajax()
的使用。
4.1、$.ajax()
一般使用该方法的第二种形式:jQuery.ajax( [settings ] )
settings是一个包含键值对的普通对象,这里列出一些有用的属性:
- url:要请求的网址,默认当前网址。
- data:要发往服务器的数据。
- method:使用的http方法,默认GET。POST和GET支持就好,可跨浏览器。method的匿名为type。
- dataType:期待接收数据的类型,如果没有指定,jQuery会通过响应的content-Type头字段来推断数据类型。指定json时,会解析响应返回javascript对象;指定xml时,会解析响应返回xml元素;指定script时,会执行该脚本;其他的都返回string。
- contentType:数据的MIME类型,默认
'application/x-www-form-urlencoded; charset=UTF-8'
- success:指定请求成功时的回调函数。
- error:指定请求失败时的回调函数。
- complete:指定请求结束时的回调函数,无论请求是否成功,在success和error回调函数之后执行。
- async:异步请求还是同步请求,默认异步请求。
- cache:是否缓存,默认true,false for dataType ‘script’ and ‘jsonp’
- context:指定回调函数中this指向的对象,默认ajax setting。
$.ajax()
返回jqXHR对象,该对象有一些方法,如jqXHR.done()
,jqXHR.fail()
,jqXHR.always()
等方法,分别对应上述success,error,complete属性。
4.2、其他
$.ajax()
看着复杂了点,其实一点也不复杂,但是jQuery也提供了一些简便的方法,对$.ajax()
进行封装。
如$.get()
的一种调用形式:jQuery.get( url [, data ] [, success ] [, dataType ] )
,看起来简单了很多,其实等于:
$.ajax({
url: url,
data: data,
success: success,
dataType: dataType
});
又如$.post()
,等于:
$.ajax({
type: "POST",
url: url,
data: data,
success: success,
dataType: dataType
});
还有$.getJSON()
,请查看文档。.load()
的可以从服务器加载html数据,插入到被选中的元素中。
ajax还有一些有用的方法,如.serialize()
可以将form表单元素编码成url查询子串的形式。.serializeArray()
则将form表单元素编码成含键值对对象的数组。
4.2.1 $.ajaxSetup
$.ajaxSetup
用于$.ajax
函数的默认选项,对于它的变种$.get
,$.post
同样生效。
CORS跨域开发需要配置前后端,现在通过$.ajaxSetup
进行前端配置:
//开发环境配置--配置ajax
let baseUrl="http://localhost:8080"
$.ajaxSetup({
//ajax请求发送前预处理
beforeSend: function(xhr, options) {
//如果是根相对地址,则加上服务端前缀
if(options.url.startsWith("/")){
options.url=baseUrl+options.url;
}
//允许发送credentials
options.xhrFields=Object.assign(
options.xhrFields==null? {} : options.xhrFields,
{ withCredentials:true }
);
}
})
//现在可以发起跨域请求了,前提是后端允许。
$.get("/hello",function(data){
console.log(data);
})
4.3、JSONP
jsonp用于跨域名获取json数据,需要server端配合,提供相应的api。
4.3.1、原理
由于cross-origin policy,浏览器不允许跨域名传输数据,但是服务端脚本却没有这种限制。同源网页通过协议、域名和端口号确定,但是即使通过jsonp,https的网页上由于安全政策也不能获得http协议传输的json数据,反之可以。
jsonp是通过<script>
元素实现的,因此脚本元素可以跨域名传输。需要服务器配合,将json数据写入到方法调用中,通过ajax将脚本加载进入,然后执行该调用。因此需要保证该网页上存在此函数。如json文件(含有方法调用),然后通过ajax获取json数据:
//此函数名在json文件中被指定了,加载json文件时会调用该函数
function jsonCallback(json){
console.log(json);
}
//使用jsonp
$.ajax({
url: "http://run.plnkr.co/plunks/v8xyYN64V4nqCshgjKms/data-2.json",
dataType: "jsonp"
});
4.3.2、使用
现在看看$.ajax()
具体如何使用,只有它的简便函数不谈,因为实现原理很简单。如果jsonp被指定,$.ajax()
将自动在url后默认添加参数callback=?
,然后加载脚本,并执行脚本中的方法调用。
callback有什么用?其他他就是个约定,约定将json数据传入哪个函数。如果服务端,没有提供这功能,那自然没有用;在github api中,它会根据callback参数自动生成对应方法调用。
jsonp
,jsonpCallback
属性分别设置url后添加的参数名(即将参数callback换成其他的)和回调函数的名字(接收json数据的函数,比如上面的jsonCallback)。jsonpCallback最好要设置,这样ajax才知道有没有成功接收到函数。
- 如果设置了jsonpCallback,并且函数存在,会继续执行success的回调函数,否则执行error的回调函数。
- 如果没有设置jsonpCallback,即使成功接收到了json数据(即jsonp的回调函数被调用),ajax还是会执行error的回调函数。
所以一般正确写法:
function logResults(json){
console.log(json);
}
$.ajax({
url: "https://api.github.com/users/jeresig",
dataType: "jsonp",
//最好指定吧。。
jsonpCallback: "logResults"
});
但是使用$.getJSON()
时,url后自己给定参数callback=?
会被当做jsonp来处理,下面的方法更为简便:
//!!!!嗯?竟然还可以这样!为什么呢?我也不知道,,,,,
$.getJSON("https://api.github.com/users/jeresig?callback=?",function(json){
console.log(json);
});
4.3.3、其他方法
使用jsonp还是有一定缺陷的,需要服务器提供这样的接口才行。当然还有其他的方法可以跨域获取json数据,不过也是有点小问题的。
- 代理:服务端是没有同源政策约束的,因此可以让服务器从其他网站上获取json数据再返回给客户端的json请求。
- CORS:网页的响应消息头字段设置了
Access-Control-Allow-Origin
,那就浏览器就允许跨域传输数据了。服务器和浏览器都可以设置该字段,服务器具体操作参考:CORS Filter;浏览器可以使用谷歌插件Allow-Control-Allow-Origin(已失效)Moesif Orign & CORS Changer
如果我需要上传数据到其他服务器呢?除了代理和CORS外,还有两种方法:
- 通过form表单上传
- 通过img,但数据不能太大。如:
var img = new Image(); img.src="http://www.otherserver.com/getxml?xml="+encodeURIComponent(yourXML);
注意,跨域后,貌似仍不能使用session
参考:https://www.sitepoint.com/jsonp-examples/
https://stackoverflow.com/a/5050047/10248407
五 其他
5.1 上传含有文件的表单
关键在于使用FormData
包裹表单数据
$("#register-form").submit(function (event) {
event.preventDefault();
$.ajax({
url:"/user/register",
type:"POST",
data:new FormData(this),
contentType:false,
processData:false,
success:function(status){
console.log(status);
}
})
})
contentType
不用设置成multipart/form-data
,为啥?不知道,测试得出的