本篇一开始咱们已经学了三大系列中的offset系列
,三大系列分别是offset
系列、scroll
系列、client
系列。学习这些有什么用呢?在后面的特效案例中,会大量的使用到获取元素的宽度、获取元素内部的宽度、获取元素距离顶部的距离等。这时候就须要用到三大系列,下面为你们一一讲解三大系列的用法。
第一章已经讲过了,详见第一章。
scroll
是用来获取盒子内容的大小和位置。scroll
家族有:scrollWidth
、scrollHeight
、scrollLeft
、scrollTop
。
一、onscroll 事件html
前面DOM的时候,咱们知道了触发事件,这里讲下onscroll事件。
对于有滚动条的盒子,可使用onscroll
注册滚动事件,每滚动一像素,就会触发该事件。ajax
示例代码: [31-scroll系列-onscroll事件.html]正则表达式
<!-- 样式部分 --> <style> #box { width: 300px; height: 300px; border: 2px solid salmon; margin: 100px auto; /* 当内容超出盒子大小的时候 自动生成滚动条 */ overflow: auto; } </style> <!-- html 部分 --> <div id="box"> 我是内容我是内容我是内容我是内容我是内容我是内容我是内容 ... ... ... 我是内容我是内容我是内容我是内容我是内容我是内容我是内容 </div> <!-- js 部分 --> <script> var box = document.getElementById('box'); box.onscroll = function() { console.log("滚了!滚了"); } </script>
效果图:编程
二、scrollWidth 和 scrollHeightsegmentfault
scrollWidth
与scrollHeight
是盒子内容的真实的宽度和高度。与和盒子大小无关,仅仅与盒子的内容有关系,不包括border
、margin
,包括padding
。
scrollWidth = padding + width; // 若是盒子里面的内容超出盒子高度的时候,这里的scrollHeight获取的就是内容的高度了 scrollHeight = padding + height;
示例代码: [32-scroll系列-scrollWidth&scrollHeight.html]数组
<!-- 样式部分 --> <style> #box { width: 100px; height: 100px; border: 10px solid salmon; margin: 50px; padding: 10px; } </style> <!-- html 部分 --> <div id="box"> 杨柳青青江水平,闻郎江上踏歌声。东边日出西边雨,道是无晴却有晴。 杨柳青青江水平,闻郎江上踏歌声。东边日出西边雨,道是无晴却有晴。 </div> <!-- js 部分 --> <script> var box = document.getElementById('box'); console.log(box.scrollWidth); // 120 console.log(box.scrollHeight); // 241 获取的是内容的高度 </script>
效果图: 浏览器
若是盒子里面的内容超出盒子高度的时候,这里的scrollHeight
获取的就是内容的高度了app
注意:框架
scrollHeight
,在内容没有超度盒子的状况下,获取到的高度是height+padding
IE8
如下的时候,即便内容没有超出盒子,获取到的高度也是内容的高度。这里就不演示了,scrollHeight
不多用到。三、scrollTop 和 scrollLeftless
scrollTop
是盒子内容被滚动条卷去的头部的高度。scrollLeft
是盒子内容被滚动条卷去的左侧的宽度。一般来讲,scroll
系列用的最多的地方就是用来获取页面被卷去的宽度和高度,很是的经常使用。
scrollTop
和 scrollLeft
存在兼容性
示例代码: [33-scroll系列-scrollTop&scrollLeft.html]
<!-- 样式部分 --> <style> body { height: 5000px; } </style> <!-- js 部分 --> <script> // 给页面注册滚动事件 window.onscroll = function() { // 滚动条滚动一次,浏览器就会获取一次被卷去的头部的高度 // 将高度赋值给title // 获取scrollTop的时候是有兼容性的:现代浏览器用的是 window.pageYOffset // IE678 用的是 document.documentElement.scrollTop document.title = window.pageYOffset || document.documentElement.scrollTop; } </script>
效果图:
完整版封装函数: [34-scroll系列-scrollTop&scrollLeft兼容性封装.html]
function getScroll() { // 返回的是一个对象,调用的时候 getScroll().top 获取页面被卷去的头部的距离 return { left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0, top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0 } }
返回值是一个对象,须要得到卷去头部的距离,只须要调用getScroll.top
便可。
scroll 系列图解:
示例代码:固定导航栏 [ 35-scroll系列-固定导航栏.html ]
offsetHeight
获取导航栏上部元素自身的高度,判断scrollTop
的高度大于等于上部元素高度的时候,说明scrollTop
到导航栏的位置了;margin-top
设置为导航栏的高度,将位置空出来;scrollTop
小于上部元素高度的时候,导航栏去掉固定定位,同时将下部元素的margin-top
设置为0
。为何一开始不直接拿导航栏到顶部的距离跟 scrollTop
比较呢?,由于导航栏固定定位以后位置就变了,恢复原来位置时的判断就不生效了
<!-- 样式部分 --> <style> * { margin: 0; padding: 0; list-style: none; } html, body { width: 100%; } .header { height: 130px; background: #FBFBFB; font: 700 28px/130px serif; color: #666; text-align: center; } .nav { height: 60px; width: 100%; background: #B9E1DC; font: 700 24px/60px serif; color: #52524E; text-align: center; } ul { display: inline-block; } li { float: left; margin-left: 60px; } .content1, .content2, .content3 { height: 800px; background: #DFFCB5; font: 700 60px/800px serif; color: #52524E; text-align: center; } .content2 { background: #FFE1B6; } .content3 { background: #CDE3EB; } .fixed { position: fixed; top: 0; left: 0; } </style> <!-- html 部分 --> <div class="header" id="header"> 顶部广告栏 </div> <div class="nav" id="nav"> <ul> <li>HOME</li> <li>ABOUT</li> <li>SERVICES</li> <li>TEAM</li> <li>CONTACT</li> </ul> </div> <div class="content1" id="con"> 内容1 </div> <div class="content2"> 内容2 </div> <div class="content3"> 内容3 </div> <!-- js 部分 --> <script> var header = document.getElementById('header'); var nav = document.getElementById('nav'); var content = document.getElementById('con'); // 封装一个scrollTop兼容性函数 function getScrollTop() { return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; } // 给页面注册滚动事件 window.onscroll = function() { // 判断广告栏header 与 滚动的scrollTop的值 // 当scrollTop > header高度的时候 让导航栏 nav 固定定位 var scrollTop = getScrollTop(); if (scrollTop >= header.offsetHeight) { // 样式中有的类名这里必定不要忘了加上去,不然就会被替换掉 nav.className = "nav fixed"; // 一旦标题栏设置了固定定位以后,就脱离标准流了,下面的内容就会顶上来, // 因此要手动给下面的内容添加一个margin-top,将导航栏的位置留下来 content.style.marginTop = nav.offsetHeight + "px"; } else { // 当scrollTop < header高度的时候 让导航栏 nav 恢复到原来的位置 // nav 取消固定定位,恢复到原来的位置,因此下面内容的margin-top也要去掉 nav.className = "nav"; // 去掉固定定位的样式,保留以前的样式 content.style.marginTop = 0; } }; </script>
效果图:
示例代码:两侧跟随小广告 [ 36-offset系列-两侧跟随小广告.html ]
scrollTop
的值scrollTop
的值,经过缓动动画设置给两侧图片(须要将以前top
的高度加上去)<!-- html 部分 --> <img src="../image/两侧固定小广告/advert.jpg" alt="" id="img1"> <img src="../image/两侧固定小广告/advert.jpg" alt="" id="img2"> <div> 内 容 . . . . . . </div> <!-- js 部分--> <script> window.onload = function() { var imgs = document.getElementsByTagName('img'); window.onscroll = function() { // 获取滚动条滚动距顶部的距离距离 var scrollTop = getScrollTop(); // 缓动跟随 animate(imgs[0], scrollTop + 300); animate(imgs[1], scrollTop + 300); }; // scrollTop兼容性处理 function getScrollTop() { return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; } // 缓动动画 function animate(element, target) { clearInterval(element.timer); element.timer = setInterval(function() { var leader = element.offsetTop; var step = (target - leader) / 20; step = step > 0 ? Math.ceil(step) : Math.floor(step); leader += step; element.style.top = leader + 'px'; if (Math.abs(target - leader) < Math.abs(step)) { element.style.top = target + "px"; clearInterval(element.timer); } }, 15); } } </script>
效果图:
示例代码:返回顶部 [ 37-offset系列-返回顶部.html ]
window.scrollTo(0, 0);
让滚动条回到(0,0)
位置。这是回到顶部的主要原理
scrollTop
的位置,判断当它距离大于等于800
的时候,让回到顶部的按钮,缓动的显示出来。当scrollTop
位置小于800
的时候,让回到顶部的按钮,缓动的隐藏起来。window.scrollTo()
target
就是scrollTo(0,target)
,因此,target
的值为0
;window.scrollTo(0,leader)
;此时的leader
仍是一个未知数,leader
其实就是当前滚动条的位置,因此,在滚动事件里,只要将leader
实时获取滚动条位置便可。<!-- 样式部分 --> <style> body { background: #FDFCE0 } div { margin: 200px auto; text-align: center; } img { width: 50px; height: 50px; background: url(../image/返回顶部/top.png); cursor: pointer; position: fixed; right: 50px; opacity: 0; bottom: 50px; } </style> <!-- html 部分 --> <div> ... 内容 ... </div> <img src="../image/返回顶部/top.png" alt="" id="top"> <!-- js 部分 --> <script src="../js/slow-animate-styles.js"></script> <script> var img = document.getElementsByTagName('img')[0]; var scrollTop; window.onscroll = function() { scrollTop = getScrollTop(); // 当滚动条位置大于等于800 的时候,让回到顶部图标缓动的显示出来 if (scrollTop >= 800) { slowAnimateStyles(img, { opacity: 100, }); img.style.display = "block"; } else { // 当位置小于800 的时候,回到顶部图标缓动的隐藏起来 slowAnimateStyles(img, { opacity: 0, }, function() { img.style.display = "none"; }); // 在这里获取leader的位置 leader = getScrollTop(); } }; // 点击img的时候,让滚动条回到顶部,这里有个知识点:window.scrollTo(0,0); 滚动条回到顶部 // 须要单首创建一个缓动动画 var timer = null; var target = 0; // 目标位置为0 即:window.scrollTo(0,target) var leader = 0; // 初始化leader img.onclick = function() { clearInterval(timer); timer = setInterval(function() { var step = (target - leader) / 10; step = step > 0 ? Math.ceil(step) : Math.floor(step); leader += step; // 此时的leader仍是一个未知数,咱们须要获取到当前滚动条的位置,而后赋值给leader, // 而且这个位置应该是实时变化的,咱们只须要在上面的滚动事件里设置下leader便可 window.scrollTo(0, leader); if (leader === 0) { clearInterval(timer); } }, 15); } // scrollTop兼容性处理 function getScrollTop() { return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; } </script>
效果图:
示例代码:楼层跳跃 [ 38-offset系列-楼层跳跃.html ]
window.scrollTo()
body
,和html
的100%
,将背景的索引与左边导航栏绑定target
,就是当前索引背景距离顶部的距离,leader
就是滚动条此时的位置<!-- html 部分 --> <ul> <li>鞋子区域</li> <li>袜子区域</li> <li>裤子区域</li> <li>裙子区域</li> <li>帽子区域</li> </ul> <ol> <li>鞋子</li> <li>袜子</li> <li>裤子</li> <li>裙子</li> <li>帽子</li> </ol> <!-- js 部分 --> <script> var colorArr = ["#B7F5DE", "#FFE9E3", "#CBF078", "#7CDFFF", "#F59292"]; var ul = document.getElementsByTagName('ul')[0]; var ol = document.getElementsByTagName('ol')[0]; var ulLis = ul.getElementsByTagName('li'); var olLis = ol.getElementsByTagName('li'); var target = 0, leader = 0, timer = null; for (var i = 0; i < colorArr.length; i++) { // 动态设置背景颜色 ulLis[i].style.background = colorArr[i]; olLis[i].style.background = colorArr[i]; // 将olLis属性绑定索引值 olLis[i].index = i; olLis[i].onclick = function() { // 点击索引,获取ul下的当前li距离顶部的距离 target = ulLis[this.index].offsetTop; clearInterval(timer); timer = setInterval(function() { var step = (target - leader) / 10; step = step > 0 ? Math.ceil(step) : Math.floor(step); leader += step; // 滚动条y方向到达leader位置 window.scrollTo(0, leader); // 判断,清除定时器 if (Math.abs(target - leader) <= Math.abs(step)) { window.scrollTo(0, target); clearInterval(timer); } }, 15); } } // 滚动事件,实时获取滚动条的位置 window.onscroll = function() { // 实时获取leader的值 leader = getScrollTop(); } // scrollTop兼容性处理 function getScrollTop() { return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; } </script>
效果图:
client
家族用于获取盒子可视区的大小。client
家族有clientWidth
、clientHeight
、clientLeft
、clientTop
。
一、clientWidth 和 clientHeight
clientWidth
:获取网页可视区域宽度 ;clientHeight
:获取网页可视区域高度;调用者不一样,意义不一样:
html/body
调用:可视区域大小border
和margin
图解clientWidth和clientHeight:
clientWidth 和 clientHeight 兼容性封装:
function getClient() { return { width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || 0, height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || 0 }; }
onresize事件:
onresize
事件会在窗口被调整大小的时候发生。
window.onresize = function(){ //事件处理程序 }
示例代码:模仿响应式布局 [ 39-client系列-模拟响应式.html ]
// 页面一进来的时候就执行一次,肯定浏览器可视区域的宽度 responsive(); // 浏览器窗口调整触发事件 window.onresize = function() { responsive(); }; // 获取浏览器宽度 function responsive() { var pageWidth = getClientWidth(); if (pageWidth >= 960) { //说明是pc document.body.style.backgroundColor = "#B7F5DE"; } else if (pageWidth >= 640) { //说明是平板 document.body.style.backgroundColor = "#CBF078"; } else { // 说明是手机 document.body.style.backgroundColor = "#F59292"; } } // clientWidth 兼容性处理 function getClientWidth() { return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || 0; }
效果图:
二、clientX 和 clientY
clientX
:鼠标距离可视区域左侧距离(event
调用) event
:事件对象,下面会讲 clientY
:鼠标距离可视区域上侧距离(event
调用)事件对象的时候,单独讲解
三、clientTop 和 clientLeft
clientTop
:盒子的上部border
的宽度clientleft
:盒子的左部border
的宽度用的不多不多,基本不会用到
clientWidth
获取的实际上是浏览器窗口的宽度,想要获取用户显示的分辨率怎么办呢?
获取用户显示器分辨率有专门的方法:window.screen.width
和window.screen.Height
示例代码:获取显示器分辨率 [ 40-screen系列-获取显示器分辨率.html ]
document.write("屏幕分辨率为:" + window.screen.width + "*" + window.screen.height);
效果图:
1280*720 分辨率的状况下:
1920*1080 分辨率的状况下:
图解三大系列区别:
width 和 height:
clientWidth
/clientHeight
:
width
+ padding
;height
+ padding
;offsetWidth
/offsetHeight
:
width
+ padding
+ border
;heigth
+ padding
+ border
;scrollWidth
/scrollHeight
:
border
);border
);top 和 left:
offsetTop
/offsetLeft
:
scrollTop
/scrollLeft
:(盒子也能够调用,必须有滚动条)
document.body.scrollTop/.....(window)
clientY
/clientX
:(clientTop
/clientLeft
值是border
)
event.clientX(event)
在触发某个事件的时候,都会产生一个事件对象
Event
,这个对象中包含全部与事件相关的一些信息,包括触发事件的元素,事件的类型以及其余与事件相关的信息。
好比:
既然事件对象中存储了这么多的信息,咱们首先须要作的就是获取到这个事件对象。获取事件对象的时候,存在浏览器的兼容问题。
现代浏览器:
获取事件对象很是的简单,只须要在注册事件的时候,指定一个形参便可。这个形参就是咱们想要获取到的事件对象。
btn.onclick = function(event){ // event就是事件对象,里面包含了事件触发时的一些信息。 // 触发事件的时候,事件是由浏览器调用,生成一个事件对象,里面包含了一些信息,当成实参传递进来了。 console.log(event); }
IE678:
获取事件对象则是另外一种方式,在事件里面,经过window.event
来获取事件对象
btn.onclick = function(){ // IE678经过window.event获取事件对象 // IE678浏览器在触发的事件的时候,生成一个事件对象,可是呢,并无当成实参传过来。会给window.event这个属性。 var event = window.event; console.log(event); }
兼容性封装: [ 41-事件对象Event兼容性.html ]
btn.onclick = function(event){ //只要用到了事件对象,就要记得处理浏览器兼容性 event = event || window.event; }
事件对象中有不少不少的属性,可是不少属性并不经常使用。咱们常常用到的是鼠标位置信息 和键盘码 相关的信息。
打印event对象咱们能够看到以下信息:
咱们能够看到一个鼠标按下的时候,它的事件对象里面有这么多属性,可是最经常使用的也就是鼠标位置信息和键盘码相关的信息。
记录了鼠标位置信息的相关属性:
screenX
与screenY
:光标相对于屏幕左上角的水平位置与垂直位置。clientX
与clientY
:光标相对于可视区左上角的水平位置和垂直位置。pageX
与pageY
:光标相对于网页(文档document
)左上角的水平位置与垂直位置(推荐使用)[ 42-事件对象-鼠标三种获取位置的属性.html ]
document.onclick = function(e) { var e = e || window.event; //获取鼠标的位置,相对的是可视区最左上角的点。(忽略滚动的距离) console.log("client(" + e.clientX + "," + e.clientY + ")"); //获取鼠标的位置,相对的页面最左上角的位置 (计算滚动的距离) console.log("page(" + e.pageX + "," + e.pageY + ")"); //获取鼠标的位置,相对的是屏幕最左上角的那个点 console.log("screen(" + e.screenX + "," + e.screenY + ")"); }
图解:
记录了键盘码的属性:
event.keyCode
:键盘按下的那个键的键盘码在鼠标事件中,记录鼠标位置信息的属性有不少,使用最多的仍是pageX
与pageY
这两个属性,可是pageX
和pageY
存在浏览器兼容性问题。
在现代浏览器中: 直接经过事件对象就能够得到pageX
与pageY
document.onclick = function (event) { event = event || window.event; console.log(event.pageX+","+event.pageY); }
在IE678中: 并无pageX
与pageY
,可是咱们能够经过scrollTop + clientY
的方式进行计算来得到pageY
。
document.onclick = function (event) { event = event || window.event; // 在IE678中使用document.documentElement.scrollTop就能够获取到scrollTop的值 alert(event.clientY + document.documentElement.scrollTop); }
pageX与pageY的兼容性封装:
function getPage(event) { return { //在IE678中使用document.documentElement.scrollLeft就能够获取到scrollLeft的值 x:event.pageX || event.clientX + document.documentElement.scrollLeft, y:event.pageY || event.clientY + document.documentElement.scrollTop } }
调用时:
getPage(event).x; getPage(event).y;
示例代码:兼容性封装测试 [ 43-事件对象-pageX&PageY兼容性处理.html ]
<!-- 样式部分 --> <style> body { height: 5000px; } </style> <!-- js 部分 --> <script> document.onclick = function(event) { event = event || window.event; alert("当前坐标为(" + getPage(event).x + "," + getPage(event).y + ")"); } function getPage(e) { return { x: e.pageX || e.clientX + document.documentElement.scrollLeft, y: e.pageY || e.clientY + document.documentElement.scrollTop } } </script>
clientX/Y
、screenX/Y
、pageX/Y
,均可以获取鼠标的位置,可是各有优劣,咱们先使用pageX/Y
获取,上面咱们已经处理pageX/Y
的兼容性了,因此这里直接使用[ 44-事件对象-跟随鼠标移动.html ]
<!-- 样式部分 --> <style> * { margin: 0; padding: 0; } body { height: 5000px; } #follow { position: absolute; width: 160px; } </style> <!-- html 部分 --> <img src="../image/鼠标跟随/2.gif" alt="" id="follow"> <!-- js 部分 --> <script> var follow = document.getElementById("follow"); //给document注册一个鼠标移动事件 document.onmousemove = function(e) { e = e || window.event; console.log(e.clientX + " " + e.clientY); follow.style.left = getPage(e).x + "px"; follow.style.top = getPage(e).y + "px"; } function getPage(e) { return { x: e.pageX || e.clientX + document.documentElement.scrollLeft, y: e.pageY || e.clientY + document.documentElement.scrollTop, } }
效果图:
经过效果图咱们能够发现,绝对定位时,当鼠标移到最右边的时候,图片会撑大浏览器自动生成滚动条,那怎么办呢?
鼠标跟随优化版 [ 45-事件对象-跟随鼠标移动优化版.html ]
只要将图片固定定位,而后经过clientX/Y
,获取可视区的位置,将它的值赋值给图片就好了
<!-- 样式部分 --> <style> * { margin: 0; padding: 0; } body { height: 5000px; } #follow { position: fixed; width: 160px; } </style> <!-- html 部分 --> <img src="../image/鼠标跟随/2.gif" alt="" id="follow"> <!-- js 部分 --> <script> var follow = document.getElementById("follow"); //给document注册一个鼠标移动事件 document.onmousemove = function(e) { e = e || window.event; console.log(e.clientX + " " + e.clientY); follow.style.left = e.clientX + "px"; follow.style.top = e.clientY + "px"; } </script>
效果图:
一、获取鼠标在盒子中的位置
当在盒子里面点击鼠标的时候,怎么得到这个鼠标在盒子中的位置呢?
没有直接的方法可以获取,可是咱们能够经过:
获取鼠标的位置 - 盒子距离顶部和左边的距离 = 鼠标在盒子里面的距离
[ 46-事件对象-获取鼠标在盒子中的位置.html ]
<!-- 样式部分 --> <style> * { margin: 0; padding: 0; } #box { width: 150px; height: 150px; background: #b7f5de; margin: 200px; } </style> <!-- html 部分 --> <div id="box"></div> <!-- js 部分 --> <script> var box = document.getElementById('box'); box.onclick = function(e) { var e = e || window.event; // 没有直接的方法可以获取,可是咱们能够经过: // 获取鼠标的位置 - 盒子距离顶部和左边的距离 = 鼠标在盒子里面的距离 var x = getPage(e).x - box.offsetLeft; var y = getPage(e).y - box.offsetTop; console.log("当前位置坐标:(" + x + "," + y + ")"); } function getPage(e) { return { x: e.pageX || e.clientX + document.documentElement.scrollLeft, y: e.pageY || e.clientY + document.documentElement.scrollTop } } </script>
效果图:
二、拖拽效果
拖拽效果在网页很常见,好比一个注册框,弹出来的时候,你能够拖动它的位置。
新事件:
onmousedown
:当鼠标按下的时候触发onmouseup
:当鼠标弹起的时候触发实现思路:
onmousedown
)事件,获取鼠标在盒子里的位置;onmousemove
)事件,鼠标移动时,将此时的鼠标距浏览器的距离减去鼠标在盒子中的距离后,赋值给盒子的top/left
onmouseup
)事件,盒子应该停在那个位置,因此清除移动事件。[ 47-事件对象-拖拽效果.html ]
<!-- 样式部分 --> <style> * { margin: 0; padding: 0; } body { height: 4000px; } #box { width: 150px; height: 150px; background: #B7F5DE; position: absolute; } </style> <!-- html 部分 --> <div id="box"></div> <!-- js 部分 --> <script> var box = document.getElementById('box'); // 鼠标按下 box.onmousedown = function(event) { event = event || window.event; // 记录按下的鼠标的位置 var x = getPage(event).x - box.offsetLeft; var y = getPage(event).y - box.offsetTop; // 按下的时候才触发鼠标移动事件 document.onmousemove = function(e) { // 鼠标点击的时候应该减去鼠标按下时在盒子中的位置 box.style.left = getPage(e).x - x + "px"; box.style.top = getPage(e).y - y + "px"; } } // 鼠标松开 // 这里为何不给盒子注册鼠标松开事件呢? 由于一旦有延迟,鼠标不在盒子上松开的时候,move事件就清除不掉了 // 因此直接给页面注册鼠标松开事件,只要鼠标松开,就清除move事件 document.onmouseup = function() { // 上面注册的移动事件会一直触发,因此在鼠标松开的时候,咱们应该将移动事件移除掉 document.onmousemove = null; } // 获取事件对象里的pageX/Y属性 function getPage(e) { return { x: e.pageX || e.clientX + document.documentElement.scrollLeft, y: e.pageY || e.clientY + document.documentElement.scrollTop } } </script>
效果图:
注意:
解决方法:
清除选中的文字
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
放大镜在开发中是一个很常见的特效,可是全部的放大镜的实现效果都是同样。
图解放大镜原理:
实现思路:
smallBox
的时候,显示 mask
和 bigBox
;smallBox
的时候,隐藏 mask
和 bigBox
;smallBox
里面的位置;smallBox
里面的位置后,要减去 mask 一半的宽高,不然鼠标不在 mask
中间显示;判断x的值限定 mask
的位置 :
mask
在小盒子里面可以移动最大的宽度和高度 0
;mask
在小盒子里面可以移动最大的宽度 = smallBox
的宽度 - mask
的宽度让大图片等比例的跟着动 :
bigImg
可以移动的距离 / mask
能移动的距离 = 大图片移动的距离 / mask
移动的距离思路图解:
示例代码: [ 48-事件对象-放大镜效果.html ]
<!-- 样式部分 --> <style> * { margin: 0; padding: 0; } #box { width: 350px; height: 350px; margin: 100px; border: 1px solid #ccc; position: relative; } #bigBox { width: 400px; height: 400px; position: absolute; top: 0; left: 360px; border: 1px solid #ccc; overflow: hidden; display: none; } .mask { width: 175px; height: 175px; background-image: url(../image/放大镜/1.png); position: absolute; top: 1px; left: 1px; cursor: move; display: none; } #smallBox { position: relative; } #box img { vertical-align: top; } #bigBox img { position: absolute; } </style> <!-- html 部分 --> <div id="box"> <div id="smallBox"> <img src="../image/放大镜/img.jpg" width="350" alt=""> <div id="mask" class="mask"></div> </div> <div id="bigBox"> <img src="../image/放大镜/img.jpg" width="800" id="bigImg" alt="" /> </div> </div> <!-- js 部分 --> <script> var box = document.getElementById('box'); var smallBox = document.getElementById('smallBox'); var bigBox = document.getElementById('bigBox'); var mask = document.getElementById('mask'); var bigImg = document.getElementById('bigImg'); // 当鼠标 通过smallBox的时候,显示 mask 和 bigBox smallBox.onmouseover = function() { mask.style.display = "block"; bigBox.style.display = "block"; }; // 当鼠标 离开smallBox的时候,隐藏 mask 和 bigBox smallBox.onmouseout = function() { mask.style.display = "none"; bigBox.style.display = "none"; }; // 鼠标在smallBox里面移动,移动 mask 和 bigImg smallBox.onmousemove = function(e) { var e = e || window.event; // mask 跟着鼠标移动 // 1- 获取鼠标在smallBox里面的位置 var spaceX = getPage(e).x - box.offsetLeft; var spaceY = getPage(e).y - box.offsetTop; // 2- 得到鼠标在smallBox里面的位置后,要减去mask一半的宽高,不然鼠标不在mask中间显示 var x = spaceX - mask.offsetWidth / 2; var y = spaceY - mask.offsetHeight / 2; // 3- 判断x的值 限定 mask的位置 // mask 在小盒子里面可以移动最大的宽度和高度 0 if (x <= 0) { x = 0; } if (y <= 0) { y = 0; } // mask 在小盒子里面可以移动最大的宽度 = smallBox的宽度 - mask的宽度 var maskMaxX = smallBox.offsetWidth - mask.offsetWidth; var maskMaxY = smallBox.offsetHeight - mask.offsetHeight; if (x >= maskMaxX) { x = maskMaxX; } if (y >= maskMaxY) { y = maskMaxY; } // 4- 设定mask的位置 mask.style.left = x + "px"; mask.style.top = y + "px"; // 5- 让大图片等比例的跟着动 // bigImg 可以移动的距离 / mask 能移动的距离 = 大图片移动的距离 / mask移动的距离 // rate :比例 var xRate = (bigImg.offsetWidth - bigBox.offsetWidth) / maskMaxX; bigImg.style.left = -xRate * x + "px"; var yRate = (bigImg.offsetHeight - bigBox.offsetHeight) / maskMaxY; bigImg.style.top = -yRate * y + "px"; }; // pageX/Y 兼容性处理 function getPage(e) { return { x: e.pageX || e.clientX + document.documentElement.scrollLeft, y: e.pageY || e.clientY + document.documentElement.scrollTop } } </script>
效果图:
前面咱们已经知道了许多触发事件的名称,可是咱们只知道了一种注册事件的方式,就是"on
+ 事件名称",下面会为你们再介绍一种注册事件的方式:addEventListener
。
onclick
、onmouseover
这种on
+ 事件名称的方式注册事件几乎全部的浏览器都支持。
注册事件:
box.onclick = function(){ //事件处理程序 }
移除事件:
box.onclick = null;
on + 事件名称注册事件的缺点:
同一个元素同一类型的事件,只能注册一个,若是注册了多个,会出现覆盖问题。
document.onclick = function(){ console.log("呵呵"); } document.onclick = function(){ console.log("哈哈"); // 最后打印的是 "哈哈",呵呵会被覆盖掉 }
现代浏览器支持的注册事件的新方式,这种方式注册的事件不会出现覆盖问题。之后在手机端就用这种注册事件的方式。
一、addEventListener 注册事件的语法:
// add:添加 Event:事件 Listener:监听器 // 三个参数: // 1. type:事件类型 "click","mouseover"... 不要再加 on了 // 2. 函数:事件触发的时候要执行的程序 // 3. useCapture(是否使用事件捕获) :true & false 默认是false document.addEventListener(type,function(){ // 事件处理程序 },useCapture);
以前咱们说过window.onload
,只能注册一个就是这个缘由,由于"on +
"注册方式会覆盖。因此若是真的须要执行两个window.onload
事件的时候,咱们就可使用addEventListener
注册:
window.addEventListener("load",function(){ // 预加载函数 1 }); window.addEventListener("load",function(){ // 预加载函数 2 });
示例代码: [ 49-注册事件-addEventListener.html ]
// 给页面注册点击事件后,会同时打印 "呵呵呵","哈哈哈" document.addEventListener("click", function() { console.log("呵呵呵"); }); document.addEventListener("click", function() { console.log("哈哈哈"); });
二、removeEventListener 移除事件的语法:
// remove:移除 Event:事件 Listener:监听器 // 三个参数: // 1. type:事件类型 "click","mouseover" // 2. 函数名:要移除的那个函数 // 3. useCapture(是否使用事件捕获) :true & false 默认是false document.addEventListener(type,fn,useCapture);
注意:
要想一个事件可以被移除,在它注册事件的时候,执行函数必需要有函数名,不能是匿名函数。由于移除事件的时候,就是移除的这个函数名。
示例代码: [ 50-移除事件-removeEventListener.html ]
// 第二个点击事件就被移除了 document.addEventListener("click", fn1); document.addEventListener("click", fn2); function fn1() { console.log("呵呵呵"); }; function fn2() { console.log("哈哈哈"); } // 移除第二个点击事件 document.removeEventListener("click", fn2);
三、IE678兼容性问题:
IE678
不支持addEventListener
与removeEventListen
两个方法,可是支持attachEvent
与detachEvnet
。
attachEvent注册事件的语法:
// attach :附上;系上;贴上 // 参数: // 1. type:事件类型 须要加上on "onclick","onmouseenter"... // 2. 函数fn:须要执行的那个事件函数 attachEvent(type, function(){ // 事件处理程序 });
attach注册时间的时候,事件类型要加上on
,没有为何,IE就这样
detachEvent的用法:
// detach :脱离 // 参数: // 1. type:事件类型 须要加上on "onclick","onmouseenter"... // 2. 函数名: 须要执行的那个事件函数名 detachEvent(type, fn);
示例代码: [ 51-注册事件-IE678方法.html ]
// IE678 下运行 document.attachEvent("onclick", fn1); document.attachEvent("onclick", fn2); function fn1() { alert("123"); }; function fn2() { alert("456"); }; // 移除第一个注册事件 document.detachEvent("onclick", fn1);
四、兼容性处理:
注册事件的新方式的解决了事件覆盖的问题,可是存在浏览器兼容性问题,所以能够进行兼容性封装。
// 添加事件兼容性封装 function addEvent(element, type, fn) { // 能力检测 if (element.addEventListener) { element.addEventListener(type, fn); } else if (element.attachEvent) { element.attachEvent("on" + type, fn); } else { //若是都不行,那就用on方式 element["on" + type] = fn; } }; //移除事件兼容性封装 function removeEvent(element, type, fn) { if (element.removeEventListener) { element.removeEventListener(type, fn); } else if (element.detachEvent) { element.detachEvent("on" + type, fn); } else { element["on" + type] = null; } }
示例代码: [ 52-注册事件-封装兼容性.html ]
// 添加事件兼容性封装 function addEvent(element, type, fn) { // 能力检测 if (element.addEventListener) { element.addEventListener(type, fn); } else if (element.attachEvent) { element.attachEvent("on" + type, fn); } else { //若是都不行,那就用on方式 element["on" + type] = fn; } }; //移除事件兼容性封装 function removeEvent(element, type, fn) { if (element.removeEventListener) { element.removeEventListener(type, fn); } else if (element.detachEvent) { element.detachEvent("on" + type, fn); } else { element["on" + type] = null; } } function fn1() { alert("呵呵"); } function fn2() { alert("哈哈"); } addEvent(document, "click", fn1); addEvent(document, "click", fn2); removeEvent(document, "click", fn1);
事件冒泡和事件捕获其实能够理解成同样东西,就是当父级元素和子元素都具备点击事件的时候,点击触发子级元素的时候父级元素也会被触发。事件冒泡是IE678
在处理事件间机制的一种说法,它执行的顺序是由内向外的,就是从子元素一直到window
。 事件捕获是火狐在处理机制时的一种说法,它执行的顺序是由外向内的,就是window
一直到子元素。
图解事件冒泡和事件捕获:
当一个元素的事件被触发时,一样的事件将会在该元素的全部祖先元素中依次被触发。这一过程被称为事件冒泡。说白了就是:当父元素和子元素都设置了点击事件的时候,触发子盒子点击事件的时候,父盒子的点击事件也会被执行。
示例代码: [ 53-事件冒泡.html ]
<!-- 样式部分 --> <style> #big-box { width: 500px; height: 500px; margin: 100px auto; vertical-align: middle; text-align: center; border: 1px solid transparent; background-color: aquamarine; } #box { width: 300px; height: 300px; margin-top: 100px; display: inline-block; background-color: darkorange; } </style> <!-- html 部分 --> <div id="big-box"> <div id="box"></div> </div> <!-- js 部分 --> <script> var bigBox = document.getElementById('big-box'); var box = document.getElementById('box'); document.onclick = function() { document.body.style.background = "#000"; } bigBox.onclick = function() { bigBox.style.background = "fuchsia"; } box.onclick = function() { // 当咱们点击box的时候,bigBox、body的点击事件 也会被触发 box.style.background = "lightgreen"; } </script>
效果图:
咱们会发现,当点击中间小盒子的时候,他的父级元素,只要有点击事件的,都被触发了,这就是事件冒泡。
正常状况下,咱们确定不想,点击子元素触发事件的时候,父元素事件也跟着触发,因此咱们就要知道一个知识点:阻止事件冒泡。在阻止事件冒泡中是存在兼容性的:
正常浏览器:
前面咱们知道了事件触发的时候,会有一个事件对象,咱们只要给事件对象加上:stopPropagation
方法便可。stopPropagation
方法不只能够阻止事件冒泡,还能够阻止事件委托
element.onclick = function (e) { e = event || window.event; //stop :中止 propagation:传播 e.stopPropagation(); }
IE678浏览器:
ie是给事件对象的属性cancelBubble
赋值
element.onclick = function (e) { e = event || window.event; e.cancelBubble = true; }
兼容性处理:
// 能力检测 element.onclick = function (e) { e = event || window.event; if(e.stopPropagation){ e.stopPropagation(); }else { e.cancelBubble = true; } }
事件捕获(capture
)是火狐浏览器提出来的,IE678
不支持事件捕获(基本上,咱们都是用事件冒泡)。事件的处理将从DOM
层次的根开始,而不是从触发事件的目标元素开始,事件被从目标元素的全部祖先元素依次往下传递。
当addEventListener
第三个参数为true时,表示事件捕获:
element.addEventListener("click", function () { console.log("哈哈哈"); },true);
事件流就是事件的三个阶段,首先发生的是捕获阶段,而后是目标阶段,最后才是冒泡阶段,对于捕获和冒泡,咱们只能干预其中的一个,一般来讲,咱们可能会干预事件冒泡阶段,而不去干预事件捕获阶段。
注意:
其实这三个阶段在执行是都会发生,可是冒泡和捕获只能执行一个,因此经过usecaptrue = false
可让捕获阶段执行可是不触发。
对于鼠标事件,事件对象中有一系列的XY
记录了鼠标的位置信息。而键盘事件中,事件对象有一个event.keyCode
属性,记录了按下去的键的键盘码。 [ 54-键盘事件-键盘码.html ]
document.onkeydown = function (e) { // 键盘按下的时候触发的事件对象 console.log(e); // keyCode: 键盘码 console.log(e.keyCode); }
键盘码对应值:
常见的键盘事件:
onkeydown
:键盘按下时触发onkeyup
:键盘弹起时触发示例代码: [ 55-键盘事件-ESC键关闭遮罩层弹出框.html ]
// 点击登录按钮 var btn = document.getElementById('btn'); // 登录框 var login = document.getElementById('login'); // 遮罩层 var bg = document.getElementById('bg'); btn.addEventListener("click", function() { login.style.display = "block"; bg.style.display = "block"; }); document.addEventListener("keyup", function(e) { e = e || window.event; // ESC 键的键盘码是27 if (e.keyCode == 27) { login.style.display = "none"; bg.style.display = "none"; } });
效果图:
咱们都看过直播,都知道弹幕的效果,下面咱们就模拟直播中的弹幕作个小案例。
实现步骤:
value
值;并生成 span
标签span
标签添加到 页面中,随机颜色 随机高度 span
动画从右向左span
标签(不删除会随着输入的内容愈来愈多影响性能)示例代码:
<style> html, body { margin: 0px; padding: 0px; width: 100%; height: 100%; font-family: "微软雅黑"; font-size: 62.5%; background: #ccc; } #page { width: 100%; height: 100%; position: relative; overflow: hidden; } #import { width: 100%; height: 60px; background: #666; position: fixed; bottom: 0px; } #content { display: inline-block; width: 430px; height: 40px; position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; margin: auto; } .title { display: inline; font-size: 25px; vertical-align: bottom; color: #fff; } #text { border: none; width: 300px; height: 30px; border-radius: 5px; font-size: 15px; padding-left: 10px; } #btn { width: 60px; height: 30px; background: #f90000; border: none; color: #fff; font-size: 15px; } span { width: 300px; height: 40px; position: absolute; overflow: hidden; color: #000; font-size: 25px; line-height: 37.5px; cursor: pointer; white-space: nowrap; } </style> <!-- 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 src="../js/animate-callback.js"></script> <script> var page = document.getElementById('page'); var text = document.getElementById('text'); var btn = document.getElementById('btn'); // 定义一个颜色数组 var colorArr = ['#FF895D', '#78BBE6', '#FF4273', '#00BBF0', '#7C73E6', '#EE2B47', '#F60C86', '#9870FC', '#F96D00', '#303481']; btn.onclick = function() { // 点击发射按钮的时候,要作的事情: // 1- 获取 input 的 value 值;并生成 span 标签 // 2- 将 span 标签添加到 page中,随机颜色 随机高度 span动画从右向左 // 3- 到达最左边的时候删除 span 标签(不删除会随着输入的内容愈来愈多影响性能) // a. 获取input的值,并清空 var content = text.value; // b. 生成span标签 添加到 page中 if (content != "" && content.trim()) { text.value = ''; var span = document.createElement('span'); page.appendChild(span); span.innerText = content; // c. 随机颜色 var randomColor = parseInt(Math.random() * colorArr.length); span.style.color = colorArr[randomColor]; // d. 随机高度 随机位置 var randomHeight = parseInt(Math.random() * 201); span.style.top = randomHeight + "px"; span.style.left = getClient().width + "px"; // e. 动画效果 animate(span, -300, function() { // f. 动画执行完成以后,回调函数中移除执行完的 span page.removeChild(span); }); } }; // text 注册键盘按下事件 当为回车按键的时候,执行发射操做 text.onkeydown = function(e) { e = e || window.event; if (e.keyCode == 13) { btn.click(); } } // 获取可视区域宽高 function getClient() { return { width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || 0, height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || 0 } } </script>
效果图:
瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为良莠不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。
一、首先瀑布流全部的图片应该保持宽度一致,高度是由内容决定。
左浮动的话,咱们能够看到第6
个盒子直接就在第4
个盒子旁边停下了,由于第4
个高度最高,挡住了它左浮动的去路。第6
个盒子是第2
行的最后一个,因此第7
个盒子只能在第3
行排列了。当排到第12
个盒子的时候,盒子会以第11
个盒子的位置为基础左浮动(这就是第12
个盒子为何没有‘跳到’第9
个盒子下面的缘由),碰到第8
个盒子后又被挡住了。
经过定位的方式是咱们实现瀑布流的最基本的原理,只要咱们动态的设置它的top
值、left
值,就能让它排列。
二、定位后肯定浏览器显示区域内,一行能放多少列图片盒子。
column = pageWidth / itemWidth
三、为了美观咱们能够加上一个空隙
column = pageWidth / (itemWidth + gap);
四、 肯定列数以后,排列第一行
1
行,因此在for
循环里就要判断一下,当i
(全部图片盒子的索引) < column
(显示列数)的时候,说明在第1
行;1
行以后,动态设置每一个图片盒子的left
值就能排好第1
行。left = i * ( itemWidth + gap );
五、第1行排列好以后,获取第1行全部图片盒子的高度
arr
,将获取到的高度存在数组中,由于第2
行排列的时候须要考虑top
值,此时只能根据第1
行图片盒子的高度来设置;onload
里面,由于图片的加载特性是:等页面都加载完以后才去请求加载,因此不写在入口函数里可能会出现高度获取不到的状况。六、排列第2行
2
行的第1
个图片盒子放置在它的下方;left
值就是高度最小列的offsetLeft
;top
值就是:第1
行高度最小列的高度(为了布局美观能够加上上下间隙gap
)。index
,后面计算会用到;七、改变最小列当前高度
八、触发resize事件
onload
里面注册一个resize
事件,只要页面一发生改变,就触发样式部分的代码。pageWidth
的宽度,这样瀑布流就会是一个响应式的效果了九、懒加载效果
30
张图片,假如一个页面中有几百张图片的时候,咱们不可能等到它都加载完再显示,全部这里引入一个懒加载的概念,咱们规定第30
张为显示的最后一张图片,当滚动条滚动到30
张的时候,应该加载下一批图片。30
图片的offsetTop
;的时候加载下面的图片。完整代码:
<!-- 样式部分 --> <style> * { margin: 0; padding: 0; position: relative; } img { width: 220px; display: block; } .item { box-shadow: 2px 2px 2px #999; position: absolute; } </style> <!-- html 部分 --> <div id="box"> <div class="item"><img src="../image/瀑布流/001.jpg" alt=""></div> . . . <div class="item"><img src="../image/瀑布流/030.jpg" alt=""></div> </div> <!-- js 部分 --> <script> var box = document.getElementById('box'); var items = box.children; // 定义每一列之间的间隙 为10像素 var gap = 10; window.onload = function() { // 一进来就调用一次 waterFall(); // 封装成一个函数 function waterFall() { // 1- 肯定列数 = 页面的宽度 / 图片的宽度 var pageWidth = getClient().width; var itemWidth = items[0].offsetWidth; var columns = parseInt(pageWidth / (itemWidth + gap)); var arr = []; for (var i = 0; i < items.length; i++) { if (i < columns) { // 2- 肯定第一行 items[i].style.top = 0; items[i].style.left = (itemWidth + gap) * i + 'px'; arr.push(items[i].offsetHeight); } else { // 其余行 // 3- 找到数组中最小高度 和 它的索引 var minHeight = arr[0]; var index = 0; for (var j = 0; j < arr.length; j++) { if (minHeight > arr[j]) { minHeight = arr[j]; index = j; } } // 4- 设置下一行的第一个盒子位置 // top值就是最小列的高度 + gap items[i].style.top = arr[index] + gap + 'px'; // left值就是最小列距离左边的距离 items[i].style.left = items[index].offsetLeft + 'px'; // 5- 修改最小列的高度 // 最小列的高度 = 当前本身的高度 + 拼接过来的高度 + 间隙的高度 arr[index] = arr[index] + items[i].offsetHeight + gap; } } } // 页面尺寸改变时实时触发 window.onresize = function() { waterFall(); }; // 当加载到第30张的时候 window.onscroll = function() { if (getClient().height + getScrollTop() >= items[items.length - 1].offsetTop) { // 模拟 ajax 获取数据 var datas = [ "../image/瀑布流/001.jpg", ... "../image/瀑布流/030.jpg" ]; for (var i = 0; i < datas.length; i++) { var div = document.createElement("div"); div.className = "item"; div.innerHTML = '<img src="' + datas[i] + '" alt="">'; box.appendChild(div); } waterFall(); } }; }; // clientWidth 处理兼容性 function getClient() { return { width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth, height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight } } // scrollTop兼容性处理 function getScrollTop() { return window.pageYOffset || document.documentElement.scrollTop; } </script>
效果图:
正则表达式:用于匹配规律规则的表达式,正则表达式最初是科学家对人类神经系统的工做原理的早起研究,如今在编程语言中有普遍的应用,常常用于表单校验,高级搜索等。
js中的正则表达式用RegExp对象表示,能够经过RegExp()构造函数来建立RegExp对象,不过更多的是经过字面量语法来建立。
/.../
正则表达式必需要有斜杠,它表示的是正则构成
构造函数的方式:
var regExp = new RegExp(/abc/); // 判断是否包含字符abc
正则字面量:/.../
var regExp = /abc/;
正则的使用:
正则表达式有一个方法:test();
有一个返回值,是布尔类型。决定参数是否符合正则表达式
console.log(/abc/.test("abc")); // true
示例代码: [ 57-正则表达式-建立正则表达式.html ]
var reg = new RegExp(/abc/); console.log(reg.test("abc")); // ture console.log(reg.test("efg")); // false console.log(reg.test("abcd")); // true 只要包含abc就正确 后面会细讲 console.log(/123/.test(123)); // true
正则表达式由一些普通字符
和元字符
组成,普通字符包括大小写字母、数字等,而元字符则具备特殊的意义。元字符:^
...
一、预约义类
正则表达式中具备特殊意义的字符。
预约义类 | 正则形式 | 释义 |
---|---|---|
. |
[^\n\r] |
除了换行和回车以外的任意字符 |
\d |
[0-9] |
数字字符 |
\D |
[^0-9] |
非数字字符 |
\w |
[a-zA-Z0-9_] |
单词字符(全部的字母数字和'_') |
\W |
[^a-zA-Z0-9_] |
非单词字符 |
\s |
[\f\r\n\t\v] |
不可见字符,包含空格 |
\S |
[^\f\r\n\t\v] |
可见字符 |
示例代码: [ 59-正则表达式-预约义类.html ]
console.log("----------------'.'---------------"); console.log(/./.test('\n')); // false console.log(/./.test('2s#2')) // true console.log("----------------'\\d'---------------"); console.log(/\d/.test(123)); // true console.log(/\d/.test('123abc')); // true console.log(/\d/.test('abc')); // false console.log("----------------'\\D'---------------"); console.log(/\D/.test(123)); // false console.log(/\D/.test('123abc')); // true console.log(/\D/.test('abc')); // true console.log("----------------'\\w'---------------"); console.log(/\w/.test(123)); // true console.log(/\w/.test('123abc_')); // true console.log(/\w/.test(' ')); // false console.log("----------------'\\W'---------------"); console.log(/\W/.test(123)); // false console.log(/\W/.test('123abc_')); // false console.log(/\W/.test(' ')); // true console.log("----------------'\\s'---------------"); console.log(/\s/.test(123)); // false console.log(/\s/.test('123abc_')); // false console.log(/\s/.test(' ')); // true console.log("----------------'\\S'---------------"); console.log(/\S/.test(123)); // true console.log(/\S/.test('123abc_')); // true console.log(/\S/.test(' ')); // false
二、简单类 [ 60-正则表达式-简单类.html ]
/ /
中什么特殊符号也不写,就是简单类
直接字符: 必须是完整的包含正则选项,只能多不能少
console.log(/levi/.test('levi')); // true console.log(/levi/.test('le')); // false console.log(/levi/.test('levi_lxh')); // true
只要完整的包含了“levi”便可(有他就行)
加上[]
: 只要包含里面任何一个便可 好比/[abcd]/
=> a,b,c,d
只要匹配项的里面有任意一项符合就返回true
console.log(/[levi]/.test("le")); // true console.log(/[levi]/.test("less")); // true console.log(/[levi]/.test("kill")); // true console.log(/[levi]/.test("ss")); // false
三、负向类
元字符^
必须出如今中括号内,表示非、取反的意思[^]
。
示例代码: [ 61-正则表达式-负向类.html ]
console.log(/[^levi]/.test("l")); // false console.log(/[^levi]/.test("le")); // false console.log(/[^levi]/.test("ec")); // true console.log(/[^levi]/.test("levi")); // false console.log(/[^levi]/.test("levi-lxh")); // true console.log(/[^levi]/.test("lxh")); // true
条件项[^levi]
,表示不能有l,e,v, i任意组合,当匹配项小于等于条件项而且包含条件项的时候,返回false
,当返回项不彻底包含条件项的时候,返回true
四、范围类:
有时候匹配的东西过多,并且类型又相同,所有输入太麻烦,咱们能够在中间加个横线
-
。
示例代码: [ 62-正则表达式-范围类.html ]
console.log(/[a-d]/.test("a")); // true console.log(/[a-d]/.test("ac123")); // true console.log(/[a-d]/.test("efg")) // false console.log(/[a-d]/.test("123")) // false
五、组合类
用中括号匹配不一样类型的单个字符串
示例代码: [ 63-正则表达式-组合类.html ]
console.log(/[a-f1-6]/.test('abs')); // true console.log(/[a-f1-6]/.test('12')); // true console.log(/[a-f1-6]/.test('sg8')); // false
咱们前面学习的正则只要有知足的条件的就会返回true,并不能作到精确的匹配。正则边界就是以什么开始,以什么结束,进行精确匹配。
一、以什么开始:
^
元字符在//
里面的时候,表示的是必须以...开始
,^
在中括号[]
内才表示取反、非的意思。
console.log(/^levi/.test('lxhlevi')); // false console.log(/^levi/.test('levilxh')); // true console.log(/^levi/.test('lxhlevilxh')); // false console.log(/^levi/.test('levilevi')); // true
二、以什么结尾:
$ 元字符表示的是必须以...结尾
console.log(/levi$/.test('lxhlevi')); // true console.log(/levi$/.test('levilxh')); // false console.log(/levi$/.test('lxhlevilxh')); // false console.log(/levi$/.test('levilevi')); // true
三、精确匹配:
^...$
表示的是精确匹配,匹配项必须是^、$
之间的内容
console.log(/^levi$/.test('lxhlevi')); // false console.log(/^levi$/.test('levilxh')); // false console.log(/^levi$/.test('lxhlevilxh')); // false console.log(/^levi$/.test('levilevi')); // false console.log(/^levi$/.test('levi')); // true console.log(/^\d$/.test('111')); // false \d表示的是0-9当中的一位数 console.log(/^\d$/.test('1')); // true
[ 64-正则表达式-正则边界.html ]
量词用来控制出现的次数,通常来讲量词和边界会一块儿使用
一、量词 *
:
表示可以出现0
次,或者跟多的次数,x >= 0
。
// 能够出现0次或者屡次 要么不出现 要么只能出现 a console.log(/^a*$/.test('abc')); // false console.log(/^a*$/.test('bbb')); // false console.log(/^a*$/.test('aab')); // false console.log(/^a*$/.test('aaa')); // true console.log(/^a*$/.test('a')); // true console.log(/^a*$/.test('')); // true
二、量词 +
:
表示可以出现1
次或者屡次,x >= 1
。
// +表示 能够出现1次或者1次以上 console.log(/^a+$/.test("a")); //true console.log(/^a+$/.test("")); //false console.log(/^a+$/.test("b")); //false console.log(/^a+$/.test("aa")); //true console.log(/^a+$/.test("aab")); //false
三、量词 ?
:
表示可以出现0
次或者1
次,x=0
或者x=1
。
// ? 表示能够出现0次或者1次 console.log(/^a?$/.test("a")); //true console.log(/^a?$/.test("")); //true console.log(/^a?$/.test("b")); //false console.log(/^a?$/.test("aa")); //false console.log(/^a?$/.test("aab")); //false
四、量词 {n}
:
表示可以出现
n
次
// * ==> {0,} console.log(/^a{0,}$/.test('a')); // true console.log(/^a{0,}$/.test('aa')); // true console.log(/^a{0,}$/.test('')); // true console.log(/^a{0,}$/.test('abc')); // fasle console.log(/^a{0,}$/.test('aaab')); // fasle
五、量词 {n,}
:
表示可以出现n
次或者n
次以上
// + ==> {1,} console.log(/^a{1,}$/.test('a')); // true console.log(/^a{1,}$/.test('aa')); // true console.log(/^a{1,}$/.test('')); // fasle console.log(/^a{1,}$/.test('abc')); // fasle console.log(/^a{1,}$/.test('aaab')); // fasle
六、量词 {n,m}
:
表示可以出现n-m次
// ? ==> {0,1} console.log(/^a{0,1}$/.test("a")); //true console.log(/^a{0,1}$/.test("")); //true console.log(/^a{0,1}$/.test("b")); //false console.log(/^a{0,1}$/.test("aa")); //false console.log(/^a{0,1}$/.test("aab")); //false
[ 65-正则表达式-量词.html ]
一、{}
大括号限定出现的次数
// 表示的是 n 重复两次 console.log(/chuan{2}/.test("chuanchuan")); // false console.log(/chuan{2}/.test("chuann")); // true console.log(/chuan{2}/.test("chuann123123")); // true
二、[]
表示一个字符出现的位置
console.log(/^[fb]oot$/.test("foot")); // true console.log(/^[fb]oot$/.test("boot")); // true
三、()
用来提高优先级
console.log(/^(chuan){2}$/.test("chuanchuan")); // true
一、验证座机号码: [ 67-正则案例-验证座机号码.html ]
021-88888888
;0515-12345678
;0
,后区必须是8
位;var reg = /^0\d{2,3}-\d{8}$/; console.log(reg.test('021-12345678')); // true console.log(reg.test('0515-88888888')); // true console.log(reg.test('0515-888880888')); // false
二、验证中文姓名 [ 68-正则案例-验证中文姓名.html ]
2-6
位之间[\u4e00-\u9fa5]
unicode
编码:万国码,其中\u4e00-\u9fa5
表示的就是包含全部汉字的unicode
编码var nameReg = /^[\u4e00-\u9fa5]{2,6}$/; console.log(nameReg.test('莫')); // false console.log(nameReg.test('小泽玛利亚')); // true console.log(nameReg.test('柯南')); // true
三、验证邮箱 [ 69-正则案例-验证邮箱.html ]
@
@
后面是字母或者数字.
.
后面是字母或者数字var mailBoxReg = /^\w+@\w+(\.\w+)+$/; console.log(mailBoxReg.test('18888888@qq.com')); // true
四、验证手机号码 [ 70-正则案例-验证手机号码.html ]
11
位数字组成13[0-9]
147
15[0-9]
177[0178]
18[0-9]
var mobileReg = /^(13[0-9]|147|15[0-9]|17[0178]|18[0-9])\d{8}$/; console.log(mobileReg.test(15812345678)); // true
五、验证QQ [ 71-正则案例-验证qq.html ]
0
5-11
位var qqReg = /^[1-9]\d{4,10}$/; console.log(qqReg.test(18888888)); // true
六、完整版表单验证 [ 72-正则案例-表单验证综合案例.html ]
<!-- 样式部分 --> <style> body { background: #ccc; } .container { margin: 100px auto; width: 400px; padding: 50px; line-height: 40px; border: 1px solid #999; background: #efefef; } label { width: 40px; display: inline-block; } span { color: red; } span { margin-left: 30px; font-size: 12px; } </style> <!-- html 部分 --> <div class="container"> <label>Q Q</label><input type="text" id="inp1"><span></span><br/> <label>手机</label><input type="text" id="inp2"><span></span><br/> <label>邮箱</label><input type="text" id="inp3"><span></span><br/> <label>座机</label><input type="text" id="inp4"><span></span><br/> <label>姓名</label><input type="text" id="inp5"><span></span><br/> </div> <!-- js 部分 --> <script> function checkReg(element, reg) { element.onblur = function() { var content = this.value; if (reg.test(content)) { this.nextElementSibling.innerHTML = "合法"; this.nextElementSibling.style.color = "green"; } else { this.nextElementSibling.innerHTML = "不合法"; this.nextElementSibling.style.color = "red"; } } } checkReg(document.getElementById("inp1"), /^[1-9]\d{4,11}$/); checkReg(document.getElementById("inp2"), /^(13[0-9]|14[57]|15[0-25-9]|17[0137]|18[0-9])\d{8}$/); checkReg(document.getElementById("inp3"), /^\w+@\w+(\.\w+)+$/); checkReg(document.getElementById("inp4"), /^0\d{2,3}-\d{7,8}$/); checkReg(document.getElementById("inp5"), /^[\u4e00-\u9fa5]{2,4}$/); </script>
效果图:
这里要补充几个正则的小知识点,好比在正则里‘|
’,表示的是或。‘g
’,表示的是global
:全局,所有。‘i
’,表示的是ignore
:忽视大小写。
一、或‘|’ :
var mobileReg = /^(13[0-9]|14[57]|15[0-25-9]|17[0137]|18[0-9])\d{8}$/;
咱们能够看到在判断手机号码前三位的时候,咱们就用到了或:“|”
二、所有‘g
’:
var str = '123123123123'; // 找到全部的1 替换成3 var newStr = str.replace(/1/g, 3); console.log(newStr); // 323323323
三、忽略大小写‘i
’:
var str2 = 'abcdAAAA'; var newStr2 = str2.replace(/a/gi, 'e'); console.log(newStr2); // ebcdeeee