本篇一開始咱們已經學了三大系列中的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