位置属性
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> *{padding: 0;margin: 0;} #box{position: relative;width: 200px;height: 200px;border: 1px solid red;padding: 10px 5px;} p{position: absolute;left:30px;top: 30px} </style> </head> <body style="height: 2000px; 2000px;"> <div id="box"> <p>我是一个段落标签</p> </div> <button id="btn">动画吧</button> <div style=" 200px;height: 200px;margin: 100px auto;border: 1px solid deepskyblue;"></div> </body> <script src="jquery-3.2.1.js"></script> <script type="text/javascript"> $(function(){ //1.获取匹配元素的相对父元素的偏移 position console.log($('p').position().left); console.log($('p').position().top); var offsetTop = $('p').position().top + 50 + 'px'; $('#btn').click(function(){ $('p').animate({top:offsetTop},1000); }); //2.获取匹配元素 相对滚动条卷起的位置信息 scrollTop scrollLeft // console.log($(document).scrollLeft()); // console.log($(document).scrollTop()); $(document).scroll(function(){ console.log($(document).scrollLeft()); console.log($(document).scrollTop()); }); // offset 获取匹配元素在当前视口的相对偏移 相对于浏览器 console.log($('#box').offset()); console.log($('p').offset().top); console.log($('p').offset().left); console.log($('#btn').offset().top); //获取元素的宽高 console.log("宽"+$('#box').width()); console.log("高"+$('#box').height()); //设置宽高 $('#box').width(400); //innerWidth / outerWidth //获取 width + 2*padding 不包括边框 获取匹配元素的内部宽度 console.log($('#box').innerWidth()); //410 // width + 2*padding + 2*border 获取匹配元素的外部宽度 console.log($('#box').outerWidth()); }) </script> </html>
01-元素坐标
.position()
返回值:Object{top,left}
获取匹配元素相对父元素的偏移位置。
当把一个新元素放在同一个容器里面另一个元素附近时,用.position()
更好用。
02-偏移
获取
.offset()
返回值:Object。获取匹配元素在当前视口的相对偏移,.offset()返回的是一个包含 top 和 left 的对象。
$("p").offset()
$('div').offset().top
$("p").offset().left
注意:jQuery不支持获取隐藏元素的偏移坐标。同样的,也无法取得隐藏元素的 border, margin, 或 padding 信息。若元素的属性设置的是 visibility:hidden
,那么我们依然可以取得它的坐标
设置
设置匹配的元素集合中每一个元素的坐标, 坐标相对于文档。
例子:
$("p").offset({ top: 10, left: 30 });
03-滚动距离
水平方向
获取:
.scrollLeft()
获取匹配元素相对滚动条左侧的偏移 文档被卷起的像素值。
//获取匹配元素相对滚动条顶部的偏移 文档被卷起的像素值
$(document).scrollTop()
$(document).scrollLeft()
//监听文档滚动的jquery方法
$(document).scroll(function(){
console.log($(document).scrollTop())
console.log($(document).scrollLeft())
})
设置:
.scrollLeft(value)
设置每个匹配元素的水平方向滚动条位置。
垂直方向
获取:
.scrollTop()
获取匹配的元素集合中第一个元素的当前迟滞滚动条的位置(页面卷走的高度)。
设置:
.scrollLeft(value)
设置每个匹配元素的垂直方向滚动条位置。
04-宽度和高度
.width()
.height()
05-innerHeight() 和 innerWidth()
.innerWidth()
描述:为匹配的元素集合中获取第一个元素的当前计算宽度值,包括padding,但是不包括border。
ps:这个方法不适用于window
和 document
对象,对于这些对象可以使用.width()代替。
.innerHeight()
描述:为匹配的元素集合中获取第一个元素的当前计算高度值,包括padding,但是不包括border。
ps:这个方法不适用于window
和 document
对象,对于这些对象可以使用.height()
代替。
06-outWidth() 和 outHeight()
.outerWidth( [includeMargin ] )
描述:获取匹配元素集合中第一个元素的当前计算外部宽度(包括padding,border和可选的margin)
.outerHeight( [includeMargin ] )
描述:获取匹配元素集合中第一个元素的当前计算外部高度(包括padding,border和可选的margin)
注:
1、includeMargin (默认: false
);
2、类型: Boolean,
一个布尔值,表明是否在计算时包含元素的margin值。
3、这个方法不适用于window
和 document
对象,可以使用.width()
代替。
案例
仿淘宝导航栏的案例
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> *{padding: 0;margin: 0;} div{width: 100%;} div img{width: 100%;} .nav{display: none;} </style> </head> <body> <div class="top"> <img src="images/top.jpg" alt="" /> </div> <div class="nav"> <img src="images/nav.jpg"/> </div> <div class= 'taobao'> <img src="images/taobao1.png"/> </div> </body> <script src="jquery-3.3.1.js"></script> <script type="text/javascript"> $(function () { var h = $('.top').height(); $(document).scroll(function () { var scrollTop = $(document).scrollTop(); if(h < scrollTop){ $('.nav').css({'display': 'block', position: 'fixed', top: 0}); }else { $('.nav').css({'display': 'none'}) } }) }) </script> </html>
选项卡
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> *{padding: 0;margin: 0;} ul{ list-style: none; } /*清除浮动产生的问题*/ #box:after{ content: ""; display: block; clear: both; } #box{width: 800px;border: 1px solid black;margin: 20px auto;background: blue;} #leftBox{width: 200px;float: left;} #leftBox li{width: 200px;height: 89px;background: red;margin-bottom: 2px;color: white;font: 50px/89px "黑体"; text-align: center;} #rightBox div{display: none;float: left; width: 600px;} #rightBox p{width:100%;height: 325px;font: 100px/325px "黑体";text-align: center;background: greenyellow } /*父元素设置display:table使它成为一个块级表格元素 * 子元素设置display:table-cell使子元素成为表格单元格,就好比是在表格中一样*/ #rightBox ul{width: 600px;display: table;} #rightBox li{display: table-cell;background: purple;height: 40px;border-right: 2px solid blue;font: 30px/40px "黑体";text-align: center;color: white;} #leftBox .active{background: yellow;color: black;} #rightBox .active{background: white;color: black;} </style> </head> <body> <div id="box"> <ul id="leftBox"> <li>a</li> <li>b</li> <li>c</li> <li>d</li> </ul> <div id="rightBox"> <div style="display: block"> <p>a1</p> <ul> <li class="active">a1</li> <li>a2</li> <li>a3</li> <li>a4</li> </ul> </div> <div> <p>b1</p> <ul> <li class="active">b1</li> <li>b2</li> <li>b3</li> <li>b4</li> </ul> </div> <div> <p>c1</p> <ul> <li class="active">c1</li> <li>c2</li> <li>c3</li> <li>c4</li> <li>c5</li> <li>c6</li> </ul> </div> <div> <p>d1</p> <ul> <li class="active">d1</li> <li>d2</li> <li>d3</li> <li>d4</li> </ul> </div> </div> </div> </body> <script src="jquery-3.3.1.js"></script> <script type="text/javascript"> $(function(){ //鼠标移入的时候 $('#leftBox li').mouseover(function(){ //修改自己的样式 $(this).addClass('active').siblings('li').removeClass('active'); //修改右边的div console.log($(this).index()); $('#rightBox div').eq($(this).index()).show().siblings('div').hide(); }); $('#rightBox li').click(function(){ $(this).addClass('active').siblings('li').removeClass('active'); var liValue = $(this).html(); $(this).parent().prev().html(liValue); }) }) </script> </html>
焦点轮播图
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> *{padding: 0;margin: 0;} ul,ol{list-style: none;} #wrap{width: 650px;height: 250px;margin: 100px auto 0;background: red;overflow: hidden;position: relative;} /*#wrap img{display: block;}*/ #wrap ul{height: 250px;position: relative;z-index: 1;} #wrap ol{height: 30px;position: absolute;z-index: 2;bottom: 0;right: 0;} #wrap>ul>li{ position: absolute; top:0; left: 0; } #wrap>ol>li{ float: left; width: 20px; height: 20px; text-align: center; line-height: 20px; border: 1px solid white; background: gray; margin-right: 5px; } #wrap>ol>li:hover{ /*设置鼠标形状*/ cursor: pointer; } #wrap li.active{ padding: 2px; color: orange; margin-top: -4px; border: 1px solid orange; } </style> </head> <body> <div id="wrap"> <ul> <!--设置绝对定位之后 脱离标准流 最后一个盒子层级提升了--> <li style="z-index: 1;"><a href="#"><img src="./images/01.jpg"/></a></li> <li><a href="#"><img src="./images/02.jpg"/></a></li> <li><a href="#"><img src="./images/03.jpg"/></a></li> <li><a href="#"><img src="./images/04.jpg"/></a></li> <li><a href="#"><img src="./images/05.jpg"/></a></li> </ul> <ol> <li class="active">1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> </ol> </div> </body> <script src="jquery-3.3.1.js"></script> <script type="text/javascript"> $(function(){ //控制层级关系的索引 var index = 0; $('#wrap>ol>li').mouseenter(function(){ index++; //修改下标的class $(this).addClass('active').siblings('li').removeClass('active'); //修改图片 $('#wrap>ul>li').eq($(this).index()).css({left:650,'z-index':index}).animate({ left:0 },1000) }) }) </script> </html>
小米官网案例
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> *{ padding: 0; margin: 0; } ul{list-style: none;} .wrap{width: 980px;height: 612px;margin: 20px auto 0;background: #f4f3f4;border: 1px solid gray;} ul li{float: left;margin-left: 10px;position: relative;overflow: hidden;width: 233px;height: 300px;} ul li p{ width: 233px; height: 100px; background: rgba(245,102,51,.7); position: absolute; bottom: -100px; text-align: center; color: white; line-height: 100px; } </style> </head> <body> <div class="wrap"> <ul> <li><a href="#"><img src="images/xiaomi_01.png"/></a><p>百度一下,你就知道</p></li> <li><a href="#"><img src="images/xiaomi_02.png"/></a><p>百度一下,你就知道</p></li> <li><a href="#"><img src="images/xiaomi_03.png"/></a><p>百度一下,你就知道</p></li> <li><a href="#"><img src="images/xiaomi_04.png"/></a><p>百度一下,你就知道</p></li> <li><a href="#"><img src="images/xiaomi_05.png"/></a><p>百度一下,你就知道</p></li> <li><a href="#"><img src="images/xiaomi_07.png"/></a><p>百度一下,你就知道</p></li> <li><a href="#"><img src="images/xiaomi_08.png"/></a><p>百度一下,你就知道</p></li> <li><a href="#"><img src="images/xiaomi_09.png"/></a><p>百度一下,你就知道</p></li> </ul> </div> </body> <script src="jquery-3.2.1.js"></script> <script type="text/javascript"> //mouseenter进入 mouseleave 离开 $('.wrap li').hover(function(){ $(this).children('p').stop(true).animate({bottom:0},100); },function(){ $(this).children('p').stop(true).animate({bottom:-100},100); }) </script> </html>
动态实现轮播图
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> *{padding: 0;margin: 0;} ul{list-style: none;} #box{ /*图片的宽高 240px 180px*/ width: 240px; height: 180px; position: relative; margin: 50px auto; overflow: hidden; } ul{ width: 960px; position: absolute; } ul li{ float: left; } p{ position: absolute; left: 80px; bottom: 30px; } p span{ color: red; display: inline-block; width: 20px; height: 20px; line-height: 20px; text-align: center; cursor: pointer; } p span.active{ color: white; background: greenyellow; } </style> </head> <body> <div id="box"> <ul> <!--显示轮播的图片--> <!--<li><img s001.jpg.jpg" alt="" /></li> <li><img s001.jpg.jpg" alt="" /></li> <li><img s001.jpg.jpg" alt="" /></li> <li><img s001.jpg.jpg" alt="" /></li>--> </ul> <p> <!--显示索引--> </p> </div> <button id="play">轮播吧!</button> <button id="stop">暂停!</button> </body> <script src="jquery-3.2.1.js"></script> <script type="text/javascript"> $(function(){ //1.获取本地的图片数据 以后再后面的课程中这些数据会从后端服务器获取 var imgArr = ['./01.jpg','./02.jpg','./03.jpg','./04.jpg']; //2.动态的生成图片 for(var i = 0; i < imgArr.length;i++){ $('ul').append("<li><img src="+imgArr[i]+"></li>") } //3.生成索引 var str = ''; $('li').each(function(i,ele){ str += "<span>"+(i+1)+"</span>" }); console.log(str); $('p').html(str); //4.默认设置索引的第一个active $('span:first').addClass('active'); var index = 0; //5.点击索引 $('span').click(function(){ $(this).addClass('active').siblings('span').removeClass('active'); //获取我当前点击的索引 index = $(this).index(); // $('ul').css("left",-240*index); $('ul').animate({ left:-240*index },100) }) var timer = null; $('#play').click(function(){ //0.开启定时器 1.索引跟着走 2.图片跟着走 timer = setInterval(next,1000); function next(){ if(index === $('li').length-1){ //图片到头了了 到第四张 index = 0; //修改span的第一个active $('p span').eq(index).addClass('active').siblings('span').removeClass('active'); //修改ul的样式 $('ul').css('left',0); }else{ index++; console.log(index); //修改后三个span标签的active $('p span').eq(index).addClass('active').siblings('span').removeClass('active'); $('ul').css('left',-240*index); } } }); $("#stop").click(function(){ clearInterval(timer); }) }) </script> </html>
事件流
想要知道这些事件是在什么时候进行调用的,就需要了解一下“事件流”的概念。例如鼠标点击事件、页面的滚动事件onscroll等等
什么是事件流?
事件流描述的是从页面中接收事件的顺序。
1、DOM事件流
“DOM2级事件”规定的事件流包括三个阶段:
① 事件捕获阶段;
② 处于目标阶段;
③ 事件冒泡阶段;
jQuery的常用事件
事件对象
Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。
事件通常与函数结合使用,函数不会在事件发生前被执行!
事件句柄 (Event Handlers)
HTML 4.0 的新特性之一是能够使 HTML 事件触发浏览器中的行为,比如当用户点击某个 HTML 元素时启动一段 JavaScript。下面是一个属性列表,可将之插入 HTML 标签以定义事件的行为。
鼠标 / 键盘属性
IE 属性
除了上面的鼠标/事件属性,IE 浏览器还支持下面的属性:
标准 Event 属性
标准 Event 方法
下面列出了 2 级 DOM 事件标准定义的方法。IE 的事件模型不支持这些方法:
jQuery的事件绑定与解绑
1、绑定事件
语法:
bind(type,data,fn)
描述:为每一个匹配元素的特定事件(像click)绑定一个事件处理器函数。
参数解释:
type (String) : 事件类型
data (Object) : (可选) 作为event.data属性值传递给事件对象的额外数据对象
fn ( Function) : 绑定到每个匹配元素的事件上面的处理函数
示例:
当每个p标签被点击的时候,弹出其文本
$("p").bind("click", function(){ alert( $(this).text() ); });
你可以在事件处理之前传递一些附加的数据。
function handler(event) { //event.data 可以获取bind()方法的第二个参数的数据 alert(event.data.foo); } $("p").bind("click", {foo: "bar"}, handler)
通过返回false来取消默认的行为并阻止事件起泡。
$("form").bind("submit", function() { return false; })
通过使用 preventDefault() 方法只取消默认的行为。
$("form").bind("submit", function(event){ event.preventDefault(); });
2、解绑事件
语法:
unbind(type,fn);
描述:
如果没有参数,则删除所有绑定的事件。
如果把在绑定时传递的处理函数作为第二个参数,则只有这个特定的事件处理函数会被删除。
参数解释:
type (String) : (可选) 事件类型
fn(Function) : (可选) 要从每个匹配元素的事件中反绑定的事件处理函数
示例:
把所有段落的所有事件取消绑定
$("p").unbind()
将段落的click事件取消绑定
$("p").unbind( "click" )
删除特定函数的绑定,将函数作为第二个参数传入。
var foo = function () {
//绑定事件和解绑事件的事件处理函数
};
$("p").bind("click mouseenter", foo); // 给p段落绑定click mouseenter事件
$("p").unbind("click", foo); // 只解绑了p段落标签的click事件
3、自定义事件
语法:
trigger(type,data);
描述:在每一个匹配的元素上触发某类事件,它触发的是由bind()注册的自定义事件。
参数解释:
type (String) : 要触发的事件类型
data (Array) : (可选)传递给事件处理函数的附加参数
示例:
给一个按钮添加自定义的事件
$('button').bind('myClick',function(ev,a,b){
//给button按钮添加的自定义事件myClick事件
})
然后通过 trigger() 触发自定义的事件
$('button').trigger('myClick',[1,2])
4、一次性事件
语法:
one(type,data,fn)
描述:
为每一个匹配元素的特定事件(像click)绑定一个一次性的事件处理函数。在每个对象上,这个事件处理函数只会被执行一次。其他规则与bind()函数相同
参数解释:
type (String) : 事件类型
data (Object) : (可选) 作为event.data属性值传递给事件对象的额外数据对象
fn (Function) : 绑定到每个匹配元素的事件上面的处理函数
示例:
当所有段落被第一次点击的时候,显示所有其文本。
$("p").one("click", function(){
//只有第一次点击的时候才会触发,再次点击不会触发了
alert( $(this).text() );
});
事件委托(事件代理)
通俗的讲,事件就是onclick,onmouseover,onmouseout,等就是事件,委托呢,就是让别人来做,这个事件本来是加在某些元素上的,然而你却加到别人身上来做,完成这个事件。
举个列子:有三个同事预计会在周一收到快递。为签收快递,有两种办法:一是三个人在公司门口等快递;二是委托给前台MM代为签收。现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。
原理就是:我们把触发事件绑定到了“父标签”上,其实就是利用了事件的冒泡性质,使得“父标签”能够代替“子标签”去实现触发事件的回调函数。
应用场景:
1.适合用事件委托的事件:click,mousedown,mouseup,keydown,keyup,keypress。
2.不适合委托:focus,blur之类的,本身就没用冒泡的特性。
解答疑问:
但是我们就有疑问了:
1.如果不同的子标签有不同的回调函数,那么如何去区分具体是哪一个子标签呢?
2.如果子标签会动态的增添或者减少,对于新增加的子标签的也可以代理么?
答案肯定是可以的:
1.每一个触发事件的回调函数中都会有一个event的参数,这个参数具有很多属性,最重要的是event.target这个属性,你打印这个属性可以获取当前触发的子标签具体是哪一个,然后可以通过event.target.nodeName.toLowerCase()来获取具体是什么元素(返回的是大写,所以我们最好转化成小写)event.target.id获取这个子标签的id,这个就可以解决我们第一个疑问
2.每次返回的这个evnet都是最新的,这样就可以解决我们第二个疑问。
那这样就能解决两个问题:
1.当列表很多,且每一行都需要做相应处理的时候,我们就没必要每一行去给它绑定事件。
2.当列表会动态增加的时候,我们不需要再为新增的元素绑定事件。
面试题:
题目:一个ul中有一千个li,如何给这一千个li绑定一个鼠标点击事件,当鼠标点击时alert出这个li的内容和li的位置坐标xy。
<ul id="ulItem"> <li id="li1">1</li> <li id="li2">2</li> <li id="li3">3</li> ... <li id="li1000">1000</li> </ul>
var ulItem = document.getElementById("ulItem"); var lis = document.getElementsByTagName("li"); for(var i=0; i<lis.length; i++){ lis[i].onclick = function(){ alert("内容:"+this.innerHTML); alert("位置:"+getElementPosition(this).x+","+getElementPosition(this).y; } } function getElementPosition(e){ var x=0,y=0; while(e != null){ x += e.offsetLeft; y += e.offsetTop; e = e.offsetParent; }<br> return {x:x, y:y}; } 缺点:1000次循环添加点击事件效率是很低的。 改进:可以利用事件冒泡的特性,来提高效率,即事件代理
var ulItem = document.getElementById("ulItem");
ulItem.onclick = function(e){
e = e || window.event;//这一行和下一行是为了兼容IE8以及之前版本
var target = e.target || e.srcElement;
if(target.tagName.toLowerCase() === "li"){
alert(target.innerHTML);
alert("位置为:"+getElementPosition(target).x+","+getElementPosition(target).y);
}
}
function getElementPosition(e){
var x=0,y=0;
while(e != null){
x += e.offsetLeft;
y += e.offsetTop;
e = e.offsetParent;
}
return {x:x, y:y};
}
on()
on() 方法在被选元素及子元素上添加一个或多个事件处理程序。
自 jQuery 版本 1.7 起,on() 方法是 bind()、live() 和 delegate() 方法的新的替代品。该方法给 API 带来很多便利,我们推荐使用该方法,它简化了 jQuery 代码库。
语法:
$(selector).on(event,childSelector,data,function)
注意:使用 on() 方法添加的事件处理程序适用于当前及未来的元素(比如由脚本创建的新元素)。
提示:如需移除事件处理程序,请使用 off() 方法。
提示:如需添加只运行一次的事件然后移除,请使用 one() 方法。
function myHandler(event) { alert(event.data.foo); } $('p').on('click', {foo: 'bar'}, myHandler)
event.data属性
event.data 属性包含当前执行的处理程序被绑定时传递到事件方法的可选数据。
示例:
对每个 <p> 元素返回通过 on() 方法传递的数据: $("p").each(function(i){ $(this).on("click",{x:i},function(event){ alert("序号:" + $(this).index() + ". 段落的数据为: " + event.data.x); }); });
on() 和 click() 的区别:
二者在绑定静态控件时没有区别,但是如果面对动态产生的控件,只有 on() 能成功的绑定到动态控件中。
以下实例中原先的 HTML 元素点击其身后的 Delete 按钮就会被删除。而动态添加的 HTML 元素,使用 click() 这种写法,点击 Delete 按钮无法删除;使用 On() 方式可以。
$("#newclick").click(function(){ $(".li").append('<li>动态添加的HTML元素click<button class="deleteclick">Delete</button></li>'); }); $("#newon").click(function(){ $(".li").append('<li>动态添加的HTML元素on<button class="deleteon">Delete</button></li>'); }); $(".delete").click(function(){ $(this).parent().remove(); }); $(".li").on('click', ".deleteon", function(){ $(this).parent().remove(); }) $(".deleteclick").click(function(){ $(this).parent().remove(); });
off()
off() 方法通常用于移除通过 on() 方法添加的事件处理程序。
自 jQuery 版本 1.7 起,off() 方法是 unbind()、die() 和 undelegate() 方法的新的替代品。该方法给 API 带来很多便利,我们推荐使用该方法,它简化了 jQuery 代码库。
注意:如需移除指定的事件处理程序,当事件处理程序被添加时,选择器字符串必须匹配 on() 方法传递的参数。
提示:如需添加只运行一次的事件然后移除,请使用 one() 方法。
语法:
$(selector).off(event,selector,function(eventObj),map)
Bind方法--参数传递与接收的三种方法
//方法一、event.data function GetCode(event) { alert(event.data.foo); } $(document).ready(function() { $("#summary").bind("click", {foo:'abc'} ,GetCode); }); //方法二、函数句柄 $("#summary").bind("click", function() { GetCode("abc") }); function GetCode(str) { } //方法三、函数闭包 function GetCode(str) { return function(){ alert(str) } } $("#summary").bind("click", GetCode("abc"));
event.target的认识
target 事件属性可返回事件的目标节点(触发该事件的节点),如生成事件的元素、文档或窗口。
event.target经常使用的属性有以下几个: event.target.nodeName //获取事件触发元素标签name event.target.id //获取事件触发元素id event.target.className //获取事件触发元素classname event.target.innerHTML //获取事件触发元素的内容 event.target.nodeName.toLowerCase() //获取事件触发元素的小写