前言
接上一次的話題,我們今天繼續學習,對於上一篇文章,有朋友認為這種文章滿大街都是(老實說,我也沒想到這么多朋友願意讀),想學javascript不如自己買一本javascript高級程序設計來讀讀,其實這些朋友的想法是正確的。
但無奈這是上面下的任務,而且我認為學習有兩個最為困難的階段:
1 入門
2 飛升
我所說的飛升到不是說非常非常厲害,也就是我兩年后想達到的水平罷了。
誠然入門不難,認為不難的同學其實是錯誤的,說他不難只能說你已經入門了,其實入門真的很難的!
就拿我來說,我入門CSS就花了很大的功夫,連現在我都覺得CSS很精秒。
我自己js入門沒有我沒有辦法斷定。什么程度算是入門,什么程度算是精通,各個人的標准都不相同,有的同學認為我js不錯,其實我自己知道我事實上還差得遠呢!
人人都想飛升,人人都想當“湯姆大叔”,我當然也想當大牛,拿寫文章來說,一來想激勵自己,二來發文章真的是一種很好的學習方式呢!
我建議大家多發技術博客,不管好壞都發!回看我兩年前的東西,只能用慘不忍睹來形容,我兩年后回看現在的博客,也許我仍然會認為慘不忍睹,那時候我便已經成為“湯姆大叔”也說不定呢,呵呵。
另外,對於不能入門的同學,迷茫是很大一個因素,二個月前我也非常迷茫,我也希望有同學能盡快找回自己的專注,丟掉他的迷茫,大家共同進步,所以這種博客我還是會發的,而且會堅持發下去。正如我讀張鑫旭博客時看到了他的那份專注從而引燃自己的那份執着。
好了,扯得很遠了,繼續我們今天的任務吧。
DOM
有些朋友記憶很差的,很不幸我就是其中之一,我從來就沒有把這個家伙事什么記清楚過!於是我就只能用中文讀出來,有一次一個朋友用英文讀了出來,我硬是不知道是什么東西!他活生生的將我帶回了高中時我花了一早上硬是記不住幾個單詞的痛苦場景!
DOM
Document Object Model 文檔對象模型
一個Window對象有一個document屬性引用了Document對象
Document對象表示窗口內容,他是一個巨大的API中的核心對象,他代表操作文檔的內容
了解DOM我們需要了解:
1 在文檔中查詢元素
2 將文檔作為節點樹來遍歷,找的節點的祖先、兄弟和后代
3 查詢和設置文檔的屬性
4 查詢、更改文檔的內容
5 創建、插入、刪除節點來修改文檔
DOM對象模型是表示和操作HTML和XML文檔內容的基本API,這個家伙說是不復雜,但是畫圖要好久呢:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>刀狂劍痴</title> </head> <body> <h1> 葉小釵</h1> <p> 葉小釵·<strong>中原劍聖</strong></p> </body> </html>
獲取文檔元素
根據ID選擇dom元素每個朋友都知道,這里真心多此一舉了,但是jquery出現后卻讓一切變得不那么明顯了:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>刀狂劍痴</title> <script type="text/javascript"> var h = document.getElementById('h'); var p = document.getElementById('p'); var strong = document.getElementById('strong'); var s = ''; </script> </head> <body> <h1 id="h"> 葉小釵</h1> <p id="p"> 葉小釵·<strong id="strong">中原劍聖</strong></p> </body> </html>
這里我一來就犯了一個錯誤,在dom還沒有生成的情況下去獲取,當然獲取不到!這里我老老實實將js放到一頁尾去了
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>刀狂劍痴</title> </head> <body> <h1 id="h"> 葉小釵</h1> <p id="p"> 葉小釵·<strong id="strong">中原劍聖</strong></p> <script type="text/javascript"> var h = document.getElementById('h'); var p = document.getElementById('p'); var strong = document.getElementById('strong'); var s = ''; </script> </body> </html>
於是我們來好好的觀察一下這些家伙:
框住的東西都是需要注意的(並且關於樣式的東西在IE中還會有兼容的問題),我們一般不必關心這些東西,但是真正用到的時候要知道如何查詢才行
name選擇
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>刀狂劍痴</title> </head> <body> <h1 id="h" name="w"> 葉小釵</h1> <p id="p"> 葉小釵·<strong id="strong">中原劍聖</strong></p> <p name="w"> 1</p> <p name="w"> 2</p> <p name="w"> 3</p> <p name="w"> 4</p> <script type="text/javascript"> var p = document.getElementsByName('w'); var s = ''; </script> </body> </html>
根據name可以選擇一個群:
標簽選擇
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>刀狂劍痴</title> </head> <body> <h1 id="h" name="w"> 葉小釵</h1> <p id="p"> 葉小釵·<strong id="strong">中原劍聖</strong></p> <p name="w"> 1</p> <p name="w"> 2</p> <p name="w"> 3</p> <p name="w"> 4</p> <script type="text/javascript"> var p = document.getElementsByTagName('p'); var s = ''; </script> </body> </html>
與上面一致,這些看起來都很簡單似的,那么我們現在要獲取一個東東,在不使用id,不使用jquery其實並不像我們想的那么簡單:
比如:我要獲取這么一個東東:
<div class="yxc"> <h1 id="h" name="w"> 葉小釵</h1> <div id="p"> 葉小釵·<strong id="strong">中原劍聖</strong></div> <div name="w"> 1</div> <div name="w"> <p> </p> <p class="come"> 來吧,獲取我吧,我是你的了1</p> <p> </p> <p class="come"> 來吧,獲取我吧,我是你的了2</p> <p class="ccc come"> </p> <p class="vvv"> </p> </div> <p name="w"> 3</p> <p name="w"> 4</p> </div>
認為簡單的同學去獲取他吧,反正就是獲取具有come css的元素,不許使用HTML5的東西哦,我不知道你痛苦不,我反正十分痛苦:
var dom = []; var ps = document.getElementsByTagName('div')[0].children[3].children; for (var i = 0, len = ps.length; i < len; i++) { var el = ps[i]; for (var j = 0; j < el.classList.length; j++) { if (el.classList[j] == 'come') { dom.push(el); break; } } }
屬性
HTML由一個標簽和一組稱為屬性飛鍵值對組成,我們一般使用getAttribute與setAttribute來獲取與設置屬性(使用.的方式也可以,但是這個更標准)。
因為屬性無法使用delete刪除,所以還提供了hasAttribute與removeAttribute來判斷標簽是否含有某屬性以及去掉標簽的某個屬性。
自定義屬性
我平時定義自定義屬性時候五花八門,所以便需要用到set/getAttribute,但是這樣卻破壞了HTML的有效性,這樣並不好。
HTML5中,提供一種解決方案,任何以data-前綴的自定義屬性認為是合法的,所以我們以后的自定義屬性還是需要注意的,
為了支持data-的屬性,HTML5特別提供dataset屬性獲取去掉前綴的屬性對象,為了兼容之前的瀏覽器,估計這個用得不多。
獲取HTML元素的內容
這個東東其實沒有什么說的:
innerHTML獲取元素內部所有文本和標簽
innerText獲取元素內部文本
outerHTML獲取標簽元素
需要注意的是,在一些瀏覽器中式不能直接操作tr與table的innerHTML的。
創建、插入、刪除
我們有時候會異步加載js,於是會有以下代碼:
function loadAsncJs(url) { var head = document.getElementsByName('head')[0]; var s = document.createElement('script'); s.setAttribute('src', url); //s.src=url head.appendChild(s); }
插入節點有兩種方法:appendChild與insertBefore
insertBefore提供兩個參數:
1 待插入節點
2 已存在節點
新節點會插入其前面,第二個參數為空的話,其表現與appendChild一致
刪除節點就比較詭異了,因為他能直接刪除,而是發生在節點的父元素上:
//比如我們要刪除el需要這樣做: el.parentNode.removeChild(el);
另外我若是想替換一個節點,可以這樣做:
el.parentNode.replace(newDom);
節點坐標與視口坐標
節點坐標便是元素相對於left與top的距離;
而視口坐標便是元素當前在瀏覽器的位置,比如y坐標本來是200但是滾動了70,那么其視口坐標便是130;
視口坐標的使用十分普遍,我們經常就會拖動元素,所以還是需要掌握的,但是這里的兼容性問題還是不少的:
獲取窗口滾動條位置
Window對象的pageXOffset與pageYOffset基本所有瀏覽器都支持,當然我們的IE會站出來說“不”!
所以我們使用的最常用的還是scrollLeft與scrollTop屬性來獲取滾動條位置
但是正常情況下查詢文檔的跟節點就能獲取,怪異模式時候變需要使用到body元素了,這個坑可大了!
function getScrollOffset(w) { w = w || window; //可能是iframe if (w.pageXOffset != null) { return { x: w.pageXOffset, y: w.pageYOffset }; } //標准瀏覽器情況下 var d = w.document; if (document.compatMode == 'CSS1Compat') { return { x: d.documentElement.scrollLeft, y: d.documentElement.scrollTop }; } //怪異模式 return { x: d.body.scrollLeft, y: d.body.scrollTop }; }
查詢元素的幾何尺寸
獲取元素的尺寸的應用也非常多,我今天才用到了呢,而且在手機上還錯了呢。。。
有些時候本來你認為比較不好獲得的東西,其實他就在那里了,getBoundingClientRect直接告訴了我們答案:
var ss = document.getElementById('w').getBoundingClientRect();
其中的width和height有一點兼容性問題,使用時候最好用right-left獲取寬度
注意:需要定位到元素上需要加上滾動距離,並且該方法的兼容性無法確定,我們還是老老實實的使用offsetWidth等屬性吧:
function getOffset(el) { if (!el) return null; return { x: el.offsetLeft, y: el.offsetTop, width: el.offsetWidth, height: el.offsetHeight }; }
判斷元素是否在某點
看到此屬性時,我首先想到的就是e屬性,典型應用就是判斷鼠標點在了什么上:
Document的elementFromPoint方法可以判斷指定坐標上有什么元素!
當鼠標信息出現在e中的那一刻,該方法的意義就不大了
有意思的東東
var cookie = document.cookie; var domain = document.domain; var referrer = document.referrer; //上一文檔的url var location = document.location;
查詢選取文本
有時候我們需要判斷用戶選取了哪些文本,並做處理:
function getSecText() { if (window.getSection) { return window.getSelection(); //html5 } else if (document.selection){ return document.selection.createRange().text; } }
BOM
瀏覽器對象模型 Browser Object Model
說白點就是window這個東東:表示瀏覽器的一個實例,是訪問瀏覽器窗口的一個接口,也是ECMAScript規定的Global對象。
意思是我們定義的所以所有的東西,都與window有關,他是客戶端給javascript程序的全局對象。
計時器
javascript的計時器有setTimeout與setInterval兩種,一個是在一定時間后執行,一個是重復執行。
這兩個東西大家應該都很熟悉了,但是在實際應用中,setTimeout卻帶給了我們不一樣的東西,比如優化!
setTimeout的優化點可以是以下地方:
① 鼠標移動標簽上加載數據(發起http請求),但我們鼠標可能無意義的划過,所以延遲點加載若是無意義請求便取消
② 無論鼠標事件或者窗口改變事件,我們都可以使用這個家伙
一個簡單的例子:
(function () { var ajax = $('#ajax'); var TIMER = null; var TIMER_STEP = 500; ajax.mousemove(loadMenu); ajax.mouseout(function () { if (TIMER) clearTimeout(TIMER); }); function loadMenu() { if (TIMER) clearTimeout(TIMER); TIMER = setTimeout(function () { //do someting }, TIMER_STEP); } })();
瀏覽器的定位和導航
對URL的請求總是非常常見的,location對象的獲取便可處理之,比如我們經常想獲取url 的參數:
function getUrlParam(name) { var args = {}; var query = document.location.search.substring(1); //去掉? var arr_param = query.split('&'); for (var i = 0, len = arr_param.length; i < len; i++) { var arr_tmp = arr_param[i].split('='); if (arr_tmp.length == 2) { args[arr_tmp[0]] = decodeURIComponent(arr_tmp[1]); } } if (name && args[name]) return args[name]; return args; } var p = getUrlParam();
結語
今天暫時到這,昨天晚上樓下有幾個當兵的喝酒聊天搞到3點鍾,我這里確實被搞崩潰了,而且又不敢去說點什么。。。。這里住了幾百戶人也沒人去說下。。。
當兵的真囂張啊。。。。我們下次繼續吧,若是我不再寫博客了就一定當兵去了,大家不要想念我。