jQuery笔记
jQuery插件中经常有这种格式代码
;(function ( $, window, document, undefined ){
//函数体内具体代码
})(jQuery, window,document);
1.最前面的分号是为了防止多个文件压缩合并后其他文件末尾没加分号而引起的错误
2.3个实参:
$是jQuery的简写,很多方法和库也有$,这里$接受jQuery对象,为了避免$变量冲突
window和document实参分别接收window、document对象,window、document对象都是再全局环境下的,而函数内window、document实际上是局部变量,不是全局的window、document对象。这样做可以提高性能,减少作用域链的查询时间
如果再函数体内需要多次调用window或document对象,这样把window或document对象当作参数传进。假如插件中不使用这两个对象,就没必要传递这两个参数了
3.还剩最后一个undefined形参,它在旧浏览器中是不支持的,直接使用会报错,为了考虑兼容,所以增加一个形参undefined
参考:
jquery插件中(function ( $, window, document, undefined )的作用
中文-What (function (window, undefined) {})(window);really means
首先区分window和document的区别
window.location === document.location
window.outerHeight的高度就是整个浏览器的高,window.innerHeight的高度是网页页面的高,也就是浏览器高减去浏览器工具栏的高度
window.innerWidth和window.outerWidth的宽度相等,都是浏览器宽
注意:innerHeight和outerHeight是有兼容性的,IE9以下不支持
该属性包含了用户屏幕的信息
大致可以分为下列:
window.screenTop;//浏览器窗口距离屏幕顶部的高度
window.screenLeft;//浏览器窗口距离屏幕左侧的宽度
window.screen//包含了屏幕的信息
window.screen.height;//屏幕的高度
window.screen.width;//屏幕的宽度
window.screen.availHeight;//屏幕可利用的高度,比如windows系统的任务栏高度去除以后就是了
window.screen.availWidth;//屏幕可利用的宽度
该属性指的是元素可视区域宽高,即padding+content
小结:
这两个元素返回的是元素周围边框的厚度,如果不指定一个边框或者不定位该元素,它的值就是0
这一堆属性用来读取元素的border的宽高
clientTop = border-top的border-width
clientLeft = border-left的border-width
这一对属性指的是元素的border+padding+content
的宽高
该属性和其内部的元素是否超出元素大小无关,只和本来设定的border以及width和height有关
offsetParent
offset*属性在不同浏览器中有不同的表现
在IE6/7中
offsetLeft = (offsetParent的padding-left) + (当前元素的margin-left)
在IE8/9/10及chrome中
offsetLeft = (offsetParent的margin-left) + (offsetParent的border宽度) + (offsetParent的padding-left) + (当前元素的margin-left)
在Firefox中
offsetLeft = (offsetParent的margin-left) + (当前元素的margin-left) + (offsetParent的padding-left)
document.body的scrollWidth和scrollHeight与div下的是有区别的
document.body下的
一、当给定宽高小于浏览器窗口时
scrollWidth通常是浏览器窗口的宽度
scrollHeight通常是浏览器窗口高度
二、当给定宽高大于浏览器窗口,且内容小于给定宽高
scrollWidth给定的高度 + 其所有的padding、margin和border
scrollHeight给定的高度 + 其所有的padding、margin和border
三、当给定宽高大于浏览器窗口,且内容大于给定宽高
scrollWidth内容高度 + 其所有的padding、margin和border
scrollHeight内容高度 + 其所有的padding、margin和border
div下的
当无滚动轴时:
scrollWidth = clientWidth = style.width + style.padding*2
当有滚动轴时:
scrollWidth = 实际内容宽度 + padding*2
scrollHeight = 实际内容高度 + padding*2
这对属性是可读写的,指的是当元素中的内容超出其宽高时,元素被卷起的高度和宽度
从上图直观看来,仿佛clientHeight
和scrollHeight
的值并不一样,然后再来对比下面的图,这是一个返回顶部按钮的demo,且鼠标已经滚动到底部:
结果,无论鼠标如何滚动,clientHeight
和scrollHeight
的值一直相等。
造成这个现象的原因在于设置了body的样式属性height:5000px
,所以clientHeight
的高就是5000px
从这里可以看出,不可以简单地认为页面可视高度就是clientHeight,要注意有没有设置body的高
然后再看:
window.innerHeight
和document.documentElement.clientHeight
相等,这里就是没有设置body的height属性
不过这只是在没有底部滚动条的情况下,如果出现底部横向滚动条就另当别论了
具体说来,window.innerHeight
包括整个DOM:内容、边框以及滚动条。
documentElement.clientHeight
不包括整个文档的滚动条,但包括<html>
元素的边框。
body.clientHeight
不包括整个文档的滚动条,也不包括<html>
元素的边框,也不包括<body>
的边框和滚动条。
二者是父子级别的关系,documentElement是html区域,body则是body区域
小结:
e.clientX
e.clientY 点击的地方距离可视窗口的距离
e.offsetX
e.offsetY 点击的地方距离父元素
e.screenX
e.screenY 点击的地方距离屏幕的距离
和jQuery直接相关的宽高的方法:
.width() .height()
.innerWidth() .innerHeight()
.outerWidth() .outerHeight()
实际值是内容的宽高,不包含padding
以width()为例
对于window和document
来说传值无效;对于普通元素来说,读写都是可以的,格式可以是width(value)
或width(function(){})
最主要的区别:
width()
返回结果无单位
css("width")
的结果有单位
它们二者的读写和前面提到的width()
和height()
一样,所以不建议在window
和document
环境下使用这两个方法
这两者可以传入一个布尔值,当传入内容是true,内容包括margin,否则不包含(默认)
除了这一点外,和innerWidth(),.innerHeight()
情况一样
scrollLeft()
:相对于水平滚动条左边的距离。如果滚动条不能滚动,该值为0
scrollTop()
类似
offset()
:相对于document的当前坐标值(相对于body左上角的left、top值)
position()
:相对于offsetParent
的当前坐标(相对于offsetParent元素左上角left、top值)
this
指的是html元素对象,可以调用html对象所拥有的属性
$(this)
指的是jQuery对象,会继承jQuery的方法
本质上,二者是JavaScript和jQuery对象之间的转换
一般来说,有
this == $(this)[0]
补充另外一个例子说明:
<a href="http://segmentfault.com/q/1010000000125418" target="_blank" data-id="1010000000125418">jQuery</a>
$('a').click(function(){
this.innerHTM==$(this).html()=='jQuery';//三者是一样的.
this.getAttribute('href')==this.href==$(this).attr('href')//三者是一样的;
this.getAttribute('target')==this.target==$(this).attr('target')//三者是一样的;
this.getAttribute('data-id')==$(this).attr('data-id')//二者是一样的;
});
一般来说,在js操作DOM的时候经常会向DOM临时增加一些参数,用作保存一些状态,或是从后端获取参数值等
在html标签上添加自定义属性就必须访问DOM,性能上并不好。如果是使用jQuery,可以尝试使用$element.data()
方法获取html标签上的data-*
自定义参数
<div id="awesome-json" data-awesome='{"game":"on"}'></div>
var gameStatus= jQuery("#awesome-json").data('awesome').game;
console.log(gameStatus);
当然,data方法不仅可以获取属性值,也可以用来设置属性值
<html>
<head>
<script type="text/javascript" src="/jquery/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#btn1").click(function(){
$("div").data("greeting", "Hello World");
});
$("#btn2").click(function(){
alert($("div").data("greeting"));
});
});
</script>
</head>
<body>
<button id="btn1">把数据添加到 div 元素</button><br />
<button id="btn2">获取已添加到 div 元素的数据</button>
<div></div>
</body>
</html>
在jQuery插件中经常会看到类似下面的代码片段:
$.fn[pluginName] = function (options) {
return this.each(function () {
if (!$.data(this, 'test_' + pluginName)) {
$.data(this, 'test_' + pluginName,
new Plugin(this, options));
}
});
}
这点很重要,因为我们在每个应用的元素上存储了对plugin实例的引用,通过data方法设置属性,允许我们检查一个元素是否已经应用了一个插件,或者需要实例化。
jQuery文档的教程一般格式如下:
$.fn[pluginName] = function ( options ) {
return this.each(function () {
if (typeof options === "string") {
var args = Array.prototype.slice.call(arguments, 1), plugin = $.data(this, 'plugin_' + pluginName);
plugin[options].apply(plugin, args);
} else if (!$.data(this, 'plugin_' + pluginName)) {
$.data(this, 'plugin_' + pluginName, new Plugin( this, options ));
}
});
};
参考:
How would I add a method to this jQuery plugin pattern?
Things I learnt creating a jQuery Plugin (Part I)
一个基本的jQuery插件demo
jQuery事件通过封装JavaScript事件来实现,比如.click()
就是onclick
的封装
和事件绑定、触发相关的api:
默认情况下,事件会冒泡,即同样的事件沿着DOM数由下至上逐级触发。
阻止冒泡的方式是event.stopPropagation()
与冒泡行为类似的是默认行为,比如点击了一个<a>
或者<button>
这类标签时,会发生默认行为,假如要阻止,可以使用event.preventDefault()
在实际使用中,我们可以通过在事件处理函数末尾添加return false
来阻止上述两种行为,所以它做了3件事:
在原生js中,绑定事件可以在DOM元素上设置类似onxx
的属性,然后在script标签对内设置对应的处理函数
<div onclick="test()"></div>
<script>
function test(){
alert("test");
}
</script>
但是这种方法不方便,所以引入了更多方法
格式:
bind(type,[data],fn)
$('.box').bind('click',function(event){})
当然也可以绑定多个事件:
$('.box').bind('click mousemove',function(event){})
还可以通过json格式在一个bind方法中绑定多个事件函数
var handler = {
click : function(){},
mousemove : function(){}
};
$('.box').bind(handler);
注意:事件处理函数内部的this,正常情况下是指向当前DOM元素
前面的格式中有一个data的可选参数,它可以是任意类型,可以通过它传入数据
var dat = { name : 'dat'};
$('.box').bind('click',dat,function(event){
alert(event.data.name); //dat
});
事件处理函数中,event.data
就是bind传入的data数据
如果该data参数传入的是布尔值,那么它可以设置是否允许默认行为和冒泡行为(false表示阻止)
bind()方法只会给当前文档中已经存在的匹配元素添加事件处理函数,如果后续动态添加元素,添加元素并不会绑定该事件处理函数,如希望绑定事件对后续添加的元素生效,可使用on()、delegate()等事件函数著作权归作者所有。
解绑通过:
$(.box).unbind('click');
实现
one()方法和bind()方法的用法一样,不过前者是用来绑定至多执行一次的事件处理函数著作权归作者所有。
格式:
on(type,[selector],[data],fn)
on()方法也是用来为指定元素的一个或多个事件绑定事件处理函数。著作权归作者所有。
bind()方法只会为页面已存在的元素绑定事件处理函数,可是on()不同,它不仅支持直接在目标元素上绑定事件,还支持在目标元素的父辈元素上委托绑定
解绑用off()方法
将事件处理函数动态绑定到指定的根元素上,由于事件冒泡特性,它被用来处理指定的子元素上的事件。
格式:
$(selector).delegate(childSelector,event,[data],function)
特点:
<div id="root">
<a>A</a>
<a>B</a>
</div>
<script>
$('#root').delegate('a', 'click', function(){
alert("click a");
});
</script>
和前面的事件绑定函数不同,trigger用来触发事件
比如:
<div class="box">123</div>
<button>模拟点击</button>
$('.box').on('click',function(){
alert(1);
});
$('button').on('click',function(){
$('.box').trigger('click');
});
load(function) 即load事件,在页面中的子元素及资源文件载入完成时触发
ready(function) 在页面中的元素已经处理完成,DOM就绪时触发
unload(function) 即unload事件,当用户离开当前页面时触发
error(function) 即error事件,在载入外部资源文件出错时触发(如载入图片出错)
resize(function) 即resize事件,当浏览器窗口大小发生变化时触发
scroll(function) 即scroll事件,当用户拖动滚动条时触发
click(function) 即click事件,在用户点击鼠标按钮时触发
dblclick(function) 即dblclick事件,在用户双击鼠标按钮时触发
focusin(function) 即focusin事件,在元素得到焦点时触发
focusout(function) 即focusout事件,在元素失去焦点时触发
hover(function)、hover(function,function) 即hover事件,在鼠标进入或离开元素时触发,若指定两个参数,进入时会触发第一个函数,离开时会触发第二个函数,否则都会触发第一个。
mousedown(function) 即mousedown事件,当在某元素上按下鼠标时触发
mouseenter(function) 即mouseenter事件,当鼠标进入某元素显示区域时触发
mouseleave(function) 即mouseleave事件,当鼠标离开某元素显示区域时触发
mousemove(function) 即mousemove事件,当鼠标在某元素显示区域内移动时触发
mouseout(function) 即mouseout事件,当鼠标离开某元素显示区域时触发
mouseover(function) 即mouseover事件,当鼠标进入某元素显示区域时触发
mouseup(function) 即mouseup事件,当按下后释放鼠标按钮时触发
mouseenter()与mouseover()、mouseleave() 与mouseup()的区别?
mouseenter()和mouseover()作用一样,但前者不支持冒泡,后者支持。
mouseleave()和mouseup()作用一样,但前者不支持冒泡,后者支持。
blur(function) 即blur事件,在元素失去焦点时触发
change(function) 即change事件,在元素的值发生变化时触发
focus(function) 即focus事件,在元素获得焦点时触发
select(function) 即select事件,在用户选中某个可选框时触发
submit(function) 即submit事件,当用户提交表单时触发
keydown(function) 即keydown事件,当用户按下一个键后触发
keypress(function) 即keypress事件,当用户按下一个键并释放后触发
keyup(function) 即keyup事件,当用户释放一个键时触发
keypress事件会在按下键盘按键时触发。它与keydown事件类似,但keypress着重的是按下该键输入了哪个字符(只有能够打印字符的键才会触发keypress),keydown着重的是按下了哪个键(按下任何键都可触发keydown)。对于诸如Ctrl、Alt、Shift、Delete、Esc等修饰性和非打印键,请监听keydown事件。著作权归作者所有。
currentTarget 返回正在处理(响应)该事件的元素
data 返回绑定事件时传递的data对象
isDefaultPrevented() 若已经调用过preventDefault()方法,返回true
isImmediatePropagationStopped() 若已经调用过stopImmediatePropation()方法,返回true
originalEvent 返回未经jQuery处理的原始DOM Event对象
pageX、pageY 返回相对于页面左上角的鼠标位置
preventDefault() 用来阻止当前事件的默认行为
relatedTarget 仅对鼠标事件有效,返回该鼠标事件有关的元素
result 返回处理该事件的最后一个事件处理函数的返回值
stopImmediatePropagation() 立即阻止调用当前事件的其他事件处理函数
stopPropagation() 阻止事件冒泡
target 返回触发事件的元素
timeStamp 返回事件发生的时间
type 返回事件类型
which 在键盘和鼠标事件中,返回用户按下的键或鼠标按钮
on和off方法是jQuery1.7+版本增加的,也推荐使用on方法
格式:
bind(type,[data],fn)
on(type,[selector],[data],fn)
二者区别在于是否含selector
这个参数,假如on方法不设置selector,那么和bind是没有区别的。
根据JavaScript的事件冒泡特性,假如父元素上注册一个事件处理函数,当子元素上发生该事件时,父元素上的事件处理函数也会一并触发
on()函数的参数selector就是为了在事件冒泡的时候,让父元素能够过滤掉子元素上发生的事件。如果使用了bind,那么就没有这个能力,子元素上发生的事件一定会触发父元素事件。
比如:
<div id="parent">
<input type="button" value="a" id="a"/>
<input type="button" value="b" id="b"/>
</div>
$("#parent").on("click","#a",function(){
alert($(this).attr("id"));
});
$("#parent").on("click","#a",function(){
alert($(this).attr("id"));
});
我们在父元素上绑定了事件处理函数,当点击子元素的任意一个按钮,都会执行事件处理函数。但是假如我们想要只点击某一个的时候才触发事件处理,那么应该使用on