第一章
1.什么是DOM
DOM: Document Object Model(文檔對象模型)
是JavaScript的方法硅堆,僅當與特殊文檔對象配合使用時(如選擇器)妆距,才能發(fā)揮作用
什么是: 專門操作網頁內容的API標準
? ? ? ? W3C指定的標準肴茄,所有瀏覽器廠商遵照實現(xiàn)
何時: 今后只要操作網頁內容击你,就必須用DOM提供的API
為什么: 為了統(tǒng)一操作網頁內容的API
? ? ? ? 用DOM標準操作網頁內容幾乎100%兼容
分為: 核心 DOM 和 HTML DOM
核心DOM: 萬能剃氧,但繁瑣
HTML DOM: 對核心DOM中部分常用API的簡化敏储,專門操作HTML文檔的API
? ? ? ? ? ?不是萬能,但簡潔
總結: 實際開發(fā)中不必區(qū)分核心DOM和HTML DOM朋鞍,優(yōu)先使用簡單的API已添,如果實現(xiàn)不了,用復雜的補充
DOM樹:
什么是: 網頁中的一切內容在內存中都是以樹形結構存儲在一起的滥酥,每項內容(元素更舞,屬性,文本)都是樹上的一個節(jié)點對象
為什么: 樹形結構是保存不確定層級深度的上下級包含關系最好的結構
根節(jié)點:樹結構都有唯一的一個根節(jié)點:document節(jié)點坎吻,所有網頁內容缆蝉,都是document的子節(jié)點
節(jié)點對象:?網頁中的每一項內容都是一個節(jié)點對象,節(jié)點對象封裝了節(jié)點可用的屬性和功能
如何:三大屬性(返回的值):
.nodeType: 節(jié)點類型
什么是: 定義了節(jié)點的類型
何時: 區(qū)分節(jié)點的類型時
為什么: 不同類型的節(jié)點可用的屬性和可執(zhí)行的操作不同
值是整數(shù):4個:?document: 9 ? 根節(jié)點
? ? ? ? ? ? ? element: ? 1 ? ?元素節(jié)點禾怠,如<html>返奉、<body>、<p>
? ? ? ? ? ? ? attribute: 2 ? ?屬性節(jié)點吗氏,元素的屬性芽偏,如a標簽的鏈接屬性
? ? ? ? ? ? ? text: ? ?? 3 ? ?文本節(jié)點,標簽中的純文本
document.createTextNode("..."): 創(chuàng)建文本節(jié)點(無標簽)弦讽,括號內為文本值
問題: nodeType無法進一步區(qū)分具體的元素名
解決:nodeName
.nodeName: 節(jié)點名(元素的標簽名)
什么是: 保存節(jié)點名稱的屬性
何時: 進一步區(qū)分具體的元素名
為什么: 不同的元素擁有的屬性和可執(zhí)行的操作都不一樣
包括: document:? #document
? ? ? element: ? 元素的標簽名(全大寫)
? ? ? attribute: 屬性名
? ? ? text: ? ?? #text(文本節(jié)點)
其實, nodeName可代替nodeType來鑒別節(jié)點類型
.nodeValue: 節(jié)點值(了解)
什么是: 保存節(jié)點的值(幾乎不用)
包括: document:? null
? ? ? element: ? null
? ? ? attribute: 屬性值
? ? ? text: ? ?? 文本內容
_______________________________________________________________________________________________
DOM 操作流程:(增刪改查+事件處理)
查找觸發(fā)事件的元素 → 綁定事件處理函數(shù) → 查找要修改的元素 → /添加/刪除/修改:內容/屬性/樣式
_______________________________________________________________________________________________
2.查找:4種:
1. 不需要查找可直接獲得的元素:
? ?document.documentElement: html
??document.head: ? ? ? ? ? ?head
??document.body: ? ? ? ? ? ?body
2. 按節(jié)點間關系查找:
何時: 如果已經獲得一個元素污尉,要找周圍元素時
包括: 2大類關系:
節(jié)點樹: 包含所有節(jié)點的完整樹結構
父子:elem.parentNode: 獲得一個節(jié)點的父節(jié)點
? ? ? elem.childNodes: ? 獲得父節(jié)點下的所有直接子節(jié)點
? ? ? elem.firstChild: ? 獲得父節(jié)點下的第一個直接子節(jié)點
? ? ? elem.lastChild: ? ?獲得節(jié)點下的最后一個直接子節(jié)點
兄弟:?elem.nextSibling: ? ? 獲得一個節(jié)點相鄰的下一個兄弟節(jié)點
? ? ? elem.previousSibling: 獲得一個節(jié)點相鄰的前一個兄弟節(jié)點
問題: 受看不見的空字符文本節(jié)點的干擾,可用元素樹解決
元素樹: 僅包含元素節(jié)點的樹結構(父子關系中與CSS有差異)
何時: 只要僅關心元素往产,不關心其它類型的節(jié)點時
父子: elem.parentElement: ? ? ? ?獲得一個節(jié)點的父元素
? ? ?elem.children:? ? ? ? ? ?獲得父元素(elem)下的所有直接子元素
? ? ?elem.firstElementChild:獲得父元素(elem)下的第一個直接子元素
? ? ?elem.lastElementChild:獲得父元素(elem)下的最后一個直接子元素
兄弟:elem.nextElementSibling: ??獲得一個元素相鄰的下一個兄弟元素
? ? ??elem.previousElementSibling:獲得一個元素相鄰的前一個兄弟元素
說明: 元素樹不是一棵新樹被碗,僅是節(jié)點樹的一個子集
優(yōu): 不受空文本的干擾
缺: IE8不兼容
比較:childNodes和children返回的不是數(shù)組,而是類數(shù)組對象
? 類數(shù)組對象: 長的像數(shù)組的對象
? VS 數(shù)組: 相同: 1.下標仿村;2. ?.length锐朴;3.用for循環(huán)遍歷
? ? ? ? ?? 不同: 類型不同,API不通用
非動態(tài)/動態(tài)集合可以直接在選擇器后面加數(shù)字下標使用: elem.children[i]
其實,childNodes和children都返回動態(tài)集合
動態(tài)集合: 不實際存儲數(shù)據(jù)蔼囊,每次訪問集合焚志,都重新查找DOM樹
? 問題: 反復訪問集合衣迷,會導致反復查找DOM樹
? 遍歷動態(tài)集合:?錯誤: for(var i=0;i<children.length;i++){...}
? ? ? ? ? ? ? ? 正確:for(var i=0,len=children.length;i<len;i++){...}(按值傳遞)
用節(jié)點間關系,遍歷查找一個父元素下所有后代節(jié)點
1. 遞歸遍歷: 2步:
? ① 定義函數(shù)僅遍歷直接子節(jié)點
? ② 對每個碰到的子節(jié)點酱酬,調用和父節(jié)點完全相同的函數(shù)
算法:深度優(yōu)先: 每當同時有子元素和兄弟元素時壶谒,總是先遍歷子元素。子元素遍歷完膳沽,才返回遍歷兄弟元素
問題: 遞歸的執(zhí)行效率極低汗菜,可用循環(huán)代替
arguments.callee: 專門指代當前正在調用的函數(shù)自己
何時: 只要遞歸,在函數(shù)內調用自己挑社,必須加arguments.callee()代替
為什么: 避免修改外層函數(shù)名后陨界,還要重復修改內部調用的函數(shù)名
強調: 因為遞歸算法效率極低,所以ES6或新版瀏覽器中已經禁止使用arguments.callee滔灶,意味著不再推薦使用遞歸算法
caller? ? 返回一個對函數(shù)的引用普碎,該函數(shù)調用了當前函數(shù)
functionName.caller:? functionName對象是所執(zhí)行函數(shù)的名稱
callee? ? 返回正被執(zhí)行的Function對象,也就是所指定的Function對象的正文
[function.]arguments.callee:? 可選項function參數(shù)是當前正在執(zhí)行的Function對象的名稱
2. 用循環(huán)代替遞歸:
節(jié)點迭代器對象(NodeIterator): 專門按照深度優(yōu)先遍歷的順序依次訪問每個子元素的對象
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 內置"深度優(yōu)先"算法
如何用節(jié)點迭代器對象:2步:
1. 創(chuàng)建節(jié)點迭代器對象:
var iterator=document.createNodeIterator( ? ? ? ? //傳遞四個參數(shù)
? parent录平,NodeFilter.SHOW_ALL麻车,null,false ? ? ?? //NodeFilter.SHOW_ALL: 遍歷所有節(jié)點
? ? ? ? ? ? ? ? ? ? ?SHOW_ELEMENT ? ? ? ? ? ? ? ? //NodeFilter.SHOW_ELEMENT: 只遍歷元素節(jié)點
);
2. 用循環(huán)反復調用NodeIterator的nextNode()函數(shù)斗这,直到返回null退出:
do{
? var node=iterator.nextNode(); ? ? ?? //返回當前節(jié)點(同時會首先返回parent元素)
? if(node!=null){
? ? console.log(node.nodeType!=3?node.nodeName:node.nodeValue); ? ?//輸出node,跳到下一個節(jié)點
? }else break; ? ? ? ? ? ? ? ? ? ? ? ? //如果返回null,就退出循環(huán)
}while(true);
3.按HTML查找:4種:
?① 按id查找一個元素:var elem=document.getElementById("id值");
? ? 強調:1.必須用document調用动猬;2.只返回一個元素
?② 按標簽名查找多個元素:?var elems=parent.getElementsByTagName("標簽名");
? ? 強調:1. 可在任意父元素上調用(標簽名為*時,可查找所有后代元素)
? ? ? ?? 2.?不但找直接子元素表箭,而且查找所有(符合條件的)后代元素
? ? ? ?? 3.返回多個元素組成的動態(tài)集合
?③ 按name屬性查找(了解):?var elems=document.getElementsByName("name的值");
? ? 何時: 查找擁有name屬性的表單元素時
? ? 強調:1. 只能用document調用
? ? ? ?? 2.?返回動態(tài)集合
?④ 按class屬性查找:?var elems=parent.getElementsByClassName("class的值");
? ? 強調:1. 可在任意父元素上調用(IE8以下不支持)
? ? ? ?? 2.?不但找直接子元素赁咙,而且找所有(符合條件的)后代元素
? ? ? ?? 3.返回動態(tài)集合
? ? ? ?? 4.只要包含指定的類名,就選擇該元素免钻,不必完全匹配
問題: 每次只能按一種條件查找彼水,如果條件復雜,代碼會很繁瑣
解決: 當查找條件復雜時极舔,要用選擇器查找
4.按選擇器查找: Selector API:2個:
① 只找一個元素:
?var elem=parent.querySelector("selector");
② 找多個元素:
?var elems=parent.querySelectorAll("selector");
強調:1. 可在任意父元素上調用
? ?? 2. 不僅查找直接子元素凤覆,且查找所有(符合條件的)后代元素
? ?? 3.返回非動態(tài)集合
? ? ? ? 非動態(tài)集合: 實際存儲數(shù)據(jù),即使反復訪問拆魏,也不會導致反復查找DOM樹(遍歷時不用緩存length)
? ?? 4. 受制于當前瀏覽器的兼容性要求(IE8以下不支持)
this關鍵字:自動獲得 當前觸發(fā)事件的元素對象(在函數(shù)中時盯桦,用于回調函數(shù)或有實參的函數(shù))
if('querySelector' in document){? ? //檢查此函數(shù)是否存在
? document.querySelector("#id");
}else{
? document.getElementById("id");
}
var elems = parent.querySelectorAll("selector");
elems是NodeList對象,無法使用一些屬于數(shù)組的函數(shù)渤刃,可將elems轉換為數(shù)組拥峦,就能使用這些函數(shù)
方法① var arrayElements = [].slice.call(elems);
方法② var arrayElements = Array.from(elems);
_______________________________________________________________________________________________
筆試:
按HTML查找 VS 按Selector API 選擇器查找
?① 返回值: 按HTML查找,返回動態(tài)集合
? ? ? ? ? ? 按Selector API 選擇器查找卖子,返回非動態(tài)集合
?② 效率: 首次查找HTML效率高
? ? ? ? ? Selector API 查找稍慢
?③ 易用性: HTML查找更繁瑣
? ? ? ? ? ? Selector API 查找更簡潔
總結:1. 如果已經獲得一個元素略号,找周圍元素用節(jié)點間關系查找
? ? ?2. 如果通過一個條件就可找到想要的元素,用HTML查找
? ? ?3. 如果查找條件復雜時,用Selector API 選擇器查找
總結返回值:
? ? 1. 凡是返回一個元素的API玄柠,如果沒找到氛琢,都返回null
? ? 2. 凡是返回多個元素的API,如果沒找到随闪,都返回空元素的集合
_______________________________________________________________________________________________
過渡動畫: 不要用display
① js中: 用支持過渡的css屬性修改樣式:width、height骚勘、opacity...
② css中: 起始樣式铐伴;過渡的新屬性;transition:all .5s linear...
凡是帶transition的元素俏讹,無論以任何手段修改樣式屬性值当宴,都自帶過渡效果
測速比較:
console.time("getChildren1"); ? ?//開始:time() 和 結束:timeEnd()里的參數(shù)必須相同才能計算時間
getChildren1(document.body);
console.timeEnd("getChildren1");
console.time("getChildren2");
getChildren2(document.body);
console.timeEnd("getChildren2");
第二章*****************************************************************************************
修改內容:
.innerHTML: 獲取或設置元素 開始標簽到結束標簽之間的HTML代碼片段(設置會清除舊元素)
? ? ? ? ? ? 單標簽無返回值,沒有標簽的文本節(jié)點返回undefined
? ? ? ? ? ? 不包括本身的標簽,但包括子標簽及其屬性(轉義字符和正文會相互轉化)
.textContent:獲取或設置元素 開始標簽到結束標簽之間的純文本內容泽疆,單標簽無返回值
? ? ? ? ? ? ?不包括任何標簽户矢、轉義字符
? ? ? ? ? ? ? ? ① 去掉了內嵌的標簽
? ? ? ? ? ? ? ? ② 將所有轉義字符翻譯為正文(而不是標簽)
? ? ? ? ? ? ? ? 強調: IE8不兼容,用.innerText代替
.value: 專門獲得或設置 表單元素的輸入內容
? 注意: var a=input.value殉疼;變量string(原始類型)梯浪,a="";無法改變input的輸入內容
_______________________________________________________________________________________________
修改屬性:
標準屬性: 2種方式訪問:
1. 核心DOM: 4個API: 所有屬性節(jié)點都保存在元素的attributes集合中 ———繁瑣
? 獲取指定屬性值: ? elem.getAttribute("屬性名") ? ? ? ? ? ? →attribute.nodeValue 屬性的值
? 修改指定屬性值: ? elem.setAttribute("屬性名","屬性值")
? 是否包含指定屬性: elem.hasAttribute("屬性名")
? 移除指定屬性: ? ? elem.removeAttribute("屬性名")
elem.getAttributeNode("屬性名"); ?→text.nodeValue 返回屬性的節(jié)點內容,表示指定的屬性和值
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .value: ?返回屬性的值
指元素的第幾個屬性(從0開始): ?elem.attributes[i];
elem.getAttributeNode(elem.attributes[i]);? →elem2.nodeValue? 返回null
2. HTML DOM: 所有標準屬性都被提前封裝在了元素對象中瓢娜,可直接用.訪問 ———簡潔挂洛,首選
?獲取屬性值: elem.屬性名
?修改屬性值: elem.屬性名="屬性值"
?是否包含: ? elem.屬性名!=""? ? ? ? /*是否為空字符串*/
?移除屬性: ? elem.屬性名=""? ? ? ? ?/*設置為空字符串*/
注意: div沒有標準屬性width/height,所以要用style.css屬性名
特殊: class屬性: class是JS語言的保留字眠砾,所以DOM中的class屬性被迫改名為className
狀態(tài)屬性: .selected ? ?.checked ? ?.disabled ? ?屬性為boolean類型虏劲,無值
? ? ? ? ? 不能用核心DOM訪問,只能用HTML DOM訪問褒颈,訪問的結果都是boolean類型
比如: checked 屬性設置或返回checkbox是否應被選中:elem.checked = true / false
注意: preventDefault 即使是在checked屬性被切換的情況下也會阻止瀏覽器改變輸入選擇框的選擇
自定義擴展屬性: 如: data-toggle="dropdown" ? ?//大寫字母會自動轉為小寫
1. 核心DOM: ———繁瑣
? ?自定義擴展屬性不能用HTML DOM訪問
2.HTML5語法: ———簡潔
定義自定義屬性: ?data-屬性名="值"
獲取/修改屬性值: elem.dataset.屬性名="屬性值" ? ? /*與HTML DOM類似*/
elem.classList 屬性返回元素的類名柒巫,該屬性用于在元素中添加,移除及切換 CSS 類
elem.classList 屬性只讀谷丸,但可用.add("class1","class2")和.remove("myStyle")方法 添加/刪除 類名
? ? ? ? ? ? ? ?? 可添加/刪除多個堡掏,若已存在則不會添加,刪除不存在的類名也不會報錯
? ? ? ? ? ? ? ? ?但不要加空格
elem.classList 返回元素的類名組成的數(shù)組
elem.classList.length 屬性返回類列表中類的數(shù)量(只讀)
elem.classList.toggle(class1, true/false) 在元素中切換類名(移除返回false淤井,添加返回true)
? ? ? 第二個參數(shù)可選布疼,設置元素是否強制添加或移除類名,不管該類名是否存在(false移除币狠,true添加)
_______________________________________________________________________________________________
修改樣式: 2種:
單獨修改一個css屬性
1. 內聯(lián): 寫在元素的style屬性中的樣式
獲取或設置內聯(lián)樣式:?elem.style.css屬性名="值"
注意:都要先找到元素游两,在使用elem.style.屬性="值"來修改屬性值,要分成兩條語句
強調: ①css屬性名都要去橫線變駝峰:
? ? ? ?? 比如: background-color->backgroundColor
? ? ? ? ? ? ?? list-style-type->listStyleType
? ? ? ② 所有css屬性名的值都是字符串(需要帶單位)
? ? ? ?? 計算前都要先去單位漩绵,轉數(shù)字再計算
問題: 實際開發(fā)中可能幾乎不包含內聯(lián)樣式贱案,用elem.style可能無法獲得任何樣式
解決: 凡是讀取樣式,都要讀取計算后的樣式: getComputedStyle(elem)
ComputedStyle:計算后的樣式: 最終應用到元素上的所有樣式的綜合,并將相對單位計算為絕對單位
如何:①?var style=getComputedStyle(elem)?//獲得計算后的所有css屬性
? ? ? ? ? ?? //無法直接獲得img的原尺寸寬高宝踪,要等圖片加載完成(.onload)后才可以獲得
? ?? ②?style.css屬性名? ? ? ? ? ? ? ? ? ? ??//從style中獲得想要的css屬性
簡寫為:getComputedStyle(elem).display? ? ?? //獲取侨糟,不建議修改
強調: 計算后的css屬性都是只讀,不允許修改瘩燥,而應使用elem.style.css屬性名秕重,進行修改
因為計算后的css屬性可能原來是共用的,一旦修改厉膀,牽一發(fā)而動全身
elem.style.cssText? ? 批量修改元素的style屬性
elem.style.cssText += elem.style.cssText + '; 樣式';? ? //避免之前的屬性被覆蓋溶耘,在前面加分號避免瀏覽器會自動去除最后一個屬性的分號
2. 內部/外部樣式表: ———危險
3步:1. 找樣式表對象: var sheet=document.stylesheets[i]
? ? 2. 找cssRule對象: var cssRule=sheet.cssRules[i]
? ? ?? 如果是keyframes,就需要繼續(xù)找下級cssRule
? ? 3. 修改cssRule的style下的css屬性值:?cssRule.style.css屬性=值
問題: 一次只能修改一個css屬性
解決: 批量修改一個元素的多個class屬性
2步: ① 先在css中將多個屬性定義為一個class
? ? ?② 在js中修改元素的className為指定的class
_______________________________________________________________________________________________
2.添加/刪除/替換:
添加: 3步:
1.創(chuàng)建空元素:?var elem=document.createElement("標簽名")
?? 比如: var a=document.createElement("a"),相當于 <a></a>
2.設置關鍵屬性:
? ?比如:a.go to tmooc";
? ? ?? 相當于 <a > go to tmooc </a>
3. 將新元素添加到 DOM 樹指定父元素下:
? ?一個新元素服鹅,必須追加到 DOM 樹下指定的父元素下凳兵,才能顯示出來
?? 3種:末尾追加:parent.appendChild(elem)? ? //最常用
? ? ? ? ? ? ? ? ? ?//把頁面上現(xiàn)有元素追加到另一個parent中,原先的元素會移動到那個parent中
? ? ?? 中間插入:parent.insertBefore(elem,child)? ? /*將新elem 插在舊child前面*/
? ? ?? 替換: ? ??parent.replaceChild(elem,child)
_______________________________________________________________________________________________
優(yōu)化: 盡量減少操作 DOM 樹(即添加企软、修改庐扫、刪除元素)
原理: 頁面加載過程: ?html -> DOM Tree
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?↓
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Render Tree ->layout-> paint(繪制)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ↑ ? ?? 計算每個元素的絕對位置
? ? ? ? ? ? ? ? ? ?? css -> CSSRules
為什么: 每修改一次DOM樹,都會反復觸發(fā)layout仗哨,降低頁面響應速度
解決: 2種:
1.如果同時添加父元素和子元素時, 就要先在內存中將子元素添加到父元素中形庭,最后再將拼好的父元素整體一次性添加到DOM樹
2. 如果父元素已經在頁面上,要同時添加多個平級子元素藻治,就要用文檔片段
文檔片段: 內存中臨時保存多個子節(jié)點的虛擬父節(jié)點
何時: 要添加多個平級子元素
如何:3步:
? ① 創(chuàng)建文檔片段:?var frag=document.createDocumentFragment();
? ② 將子元素臨時追加到frag中:?frag.appendChild(elem);(在這之前先創(chuàng)建子元素碘勉,并設置關鍵元素)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //比如: 可以先設置left/top、canvas先畫好
? ③ 將frag整體追加到 DOM 樹:?parent.appendChild(frag);
說明: frag不會成為實際頁面元素桩卵,將子元素添加到DOM樹后验靡,frag自動釋放,不占用頁面空間
刪除:parent.removeChild(child);
第三章*****************************************************************************************
1.HTML DOM常用對象:
Image: 指代頁面上一個img元素
創(chuàng)建: ? ?var img=new Image();
指定屬性:img.src="banner_01.jpg";
追加: ? ?parent.appendChild(img);
圖片加載完成再進行操作:
方法① img.onload = function(){ ... }
方法②?img.onreadystatechange = function(){ if(this.readyState == "complete"){ ... }
Select: 指代頁面上一個<select>元素
屬性:sel.selectedIndex ? 獲得當前選中項的下標位置
? ?? sel.value ? ? ? ? ? 獲得當前sel的值(value),如果選中項沒有value,則用內容(innerHTML)代替
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?<select>元素的值就是當前選中項的值
? ?? sel.options ? ? ? ?? 獲得當前sel下所有option元素的集合
? ?? sel.options.length ? 選項的個數(shù) <=> sel.length
? ?? sel.options.length=0 清除所有選項 <=> sel.length=0
? ? ?sel.options[sel.selectedIndex].text?獲取選中項的文本
方法:① sel.add(option) ? ? 向sel末尾追加一個option
? ? ? ? 強調: 不支持文檔片段(frag)(用frag時不用.add)
? ? ?② sel.remove(i)?? 移除i位置的選項
事件:sel.onchange? 當選中項發(fā)生改變時觸發(fā)此事件函數(shù)
Option: 指代頁面上一個option元素
創(chuàng)建/設置屬性:var opt=new Option(text,value)? ?? /*內容和值一起創(chuàng)建*/
屬性:opt.text代替opt.innerHTML
_______________________________________________________________________________________________
Table:指代一個table元素:?管著行分組: 創(chuàng)建雏节,刪除胜嗓,獲取
創(chuàng)建行分組: var thead=table.createTHead();
? ? ? ? ? ? var tbody=table.createTBody();
? ? ? ? ? ? var tfoot=table.createTFoot();
刪除行分組: table.deleteTHead();
? ? ? ? ? ? table.deleteTFoot();
獲取行分組: table.tHead
? ? ? ? ? ? table.tBodies[i]
? ? ? ? ? ? table.tFoot
行分組:tHead tBody tFoot: 管著行tr
創(chuàng)建行: var tr=行分組.insertRow(i);
? ? ? ? 說明: 如果i位置有行,則原位置的行向后順移
固定套路: 1.末尾追加新行: 行分組.insertRow();
? ? ? ? ? 2.開頭插入新行: 行分組.insertRow(0);
刪除行: 行分組.deleteRow(i) ? ? /*刪除當前行分組中下標為i的行*/
獲取所有行: 行分組.rows
行:管著格:
創(chuàng)建格: var td=tr.insertCell(i)
? ? 固定套路:末尾追加: tr.insertCell()
? ? 強調: insertCell只能創(chuàng)建td
刪除格: tr.deleteCell(i)
獲取格: tr.cells
刪除行:2種:
1. 行分組.deleteRow(i)
?? i是行在行分組內的相對下標位置, 無法直接獲得
2. table.deleteRow(i)
?? i是行在整個table中的絕對下標位置钩乍,可直接獲得:?tr.rowIndex ? ?表示tr在整個表格中的位置
固定套路:刪除行: table.deleteRow(tr.rowIndex)
_______________________________________________________________________________________________
三大對話框: 彈出的是窗口(對話框辞州,css/js改變的是body),無法改變標題寥粹、樣式等
alert(): 警告框
prompt(str1,str2): 輸入框
? str1:?輸入框的提示信息
? str2:?文本框的默認值变过,默認為空
? 返回值:?點擊確定返回文本框中的內容,點擊取消返回null
confirm(): 確認框(有確認和取消操作的對話框)
? 何時:只要執(zhí)行危險的操作前(提交更新涝涤、刪除)都要先確認再執(zhí)行操作
? 如何:var bool=confirm("提示消息");
? ? ? ? 如果點確定膀值,就返回true此虑,執(zhí)行操作
? ? ? ? 否則搂擦,就返回false雳灵,不執(zhí)行操作
Form: 代表頁面上一個form元素
獲取:var form=document.forms[i/'id']? ?獲取頁面上的第i個form元素或為此id的form元素
屬性: form.elements ? ? ? ? 獲得表單中的所有表單元素: input select button textarea
? ? ? form.elements.length ?獲得表單中表單元素的個數(shù) <=>?form.length
方法:form.submit(); ? ?? 用程序手動提交表單(定義一個變量,提交前修改其值,防止重復提交)
何時: 只要希望通過自定義的驗證去決定是否提交表單: 2種
1.?<input type="button"/>(代替input->submit: 自動提交,不驗證)在<input type="button"/>的單擊事件中自己手動調用form.submit();
2.<input type="submit"/>?用 e.preventDefault() 阻止表單默認提交
事件: form.onsubmit=function(){ }
獲取表單中的表單元素:var elem=form.elements[i/id/name]
簡寫:如果表單元素有name屬性: ? form.name
? ? ?如果表單元素沒有name屬性: form.elements[form.length-2] ? ?獲得倒數(shù)第2個按鈕(元素)
方法:elem.focus(); ?讓elem獲得焦點
? ? ?elem.blur(); ? 讓elem失去焦點
_______________________________________________________________________________________________
2.什么是BOM:Browser Object Model(瀏覽器對象模型)
BOM: 專門操作瀏覽器窗口/軟件的API(沒有標準辨宠,瀏覽器不同)
window:2個角色:
? 1. 代替ES遗锣、NodeJS中的Global充當全局作用域對象
? 2. 封裝所有瀏覽器內置的/DOM/BOM 的API
window的功能: 打開和關閉窗口,彈出對話框...
包括: history: ? 保存當前窗口打開后嗤形,成功訪問過的url的歷史記錄棧精偿,控制前進后退
? ? ? location:? 保存瀏覽器正在打開的url的地址
? ? ? document:? 封裝頁面內容和 DOM API的根對象
? ? ? navigator: 保存瀏覽器的配置信息
? ? ? screen: ?? 保存顯示設備的信息
? ? ? event: ? ? 定義事件對象
_______________________________________________________________________________________________
3.打開和關閉窗口:
打開一個新窗口: window.open("url","name")
所有在window下,都可省略window.
name: 內存中每個窗口都有一個唯一的name屬性
瀏覽器規(guī)定: 同一個name屬性的窗口只能打開1個
? ? ? ? ? ? 后打開的同名窗口會覆蓋先打開的
預定義name: _self: 用當前窗口的name打開新窗口
? ? ? ? ? ? ? ? ? ?結果: 新窗口替換當前窗口
? ? ? ? ? ? _blank: 不指定name屬性赋兵,用空name打開新窗口还最,讓瀏覽器隨機分配name
? ? ? ? ? ? ? ? ? ? 結果: 每個窗口的name都不一樣,就可打開多個
第三個參數(shù)可指定窗口樣式:
? 如:?var?newWindow = window.open("url","_blank",'top=100,left=100,width=300,height=300');
? ? ? top/left:?窗口頂部距離屏幕頂部/左端的像素數(shù)(指定寬高時有效)
? ? ? width/height:?窗口的寬/高毡惜,單位像素
? 可使用newWindow.close()關閉打開的窗口
打開和關閉窗口: 4種:
1. 在當前窗口打開,可后退:
? ?HTML: <a href="url" target="_self"></a>
? ?js: open("url","_self")
2. 在當前窗口打開斯撮,不可后退:
?? 當前窗口每打開一個新url经伙,都會將新url保存在history中
?? 如果新url是追加進history中,則可后退勿锅;如果新url將當前url替換掉帕膜,則無法后退到此頁面(其它正常)
? ?HTML: 無法實現(xiàn)
??js:location.replace("url")
3. 在新窗口打開,可打開多個:
?? HTML: <a href="url" target="_blank"></a>
?? js: open("url","_blank")
4. 在新窗口打開溢十,只能打開一個:
?? HTML: <a href="url" target="自定義name"></a>
??js: open("url","自定義name")
close(): ?關閉頁面
窗口大小: 文檔顯示區(qū)的大小:
寬:?window.innerWidth? ? ? ? 高:?window.innerHeight
body的寬垮刹、高(最短,不包括border、滾動條):? document.body.clientWidth/clientHeight;
屏幕可用工作區(qū)寬度(實際寬度):? window.screen.availHeight/Width;
_______________________________________________________________________________________________
4.定時器:2種:
周期性定時器:(盡量不要嵌套定時器)
若想要使等待的時間不斷變化张弛,只能在回調函數(shù)中荒典,先清除定時器,再啟動定時器(不要用var)
var reqParam = {
? arr: [0, 10000, 60000, 180000, 420000],? //請求間隔(0表示倒計時結束立即請求一次)
? max: [1, 10, 10, 10, 10],? ? ? ? ? ? ? ? //每種間隔最大請求次數(shù)
? index: 0,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //請求數(shù)組的當前下標
??count: 0,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //當前請求次數(shù)
??timer: null,? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//初始化請求次數(shù)定時器
??countTimer: null,? ? ? ? ? ? ? ? ? ? ? ? //初始化倒計時定時器
??ajaxType: 'jsonp',? ? ? ? ? ? ? ? ? ? ? ?//發(fā)起ajax請求的方式(可在單獨頁面中定義)
??jsonp: 'jsonp_callback',? ? ? ? ? ? ? ? ?//jsonp跨域函數(shù)名
? countdown: true,? ? ? ? ? ? ? ? ? ? ? ? ?//是否倒計時
? desc: '等待開獎',? ? ? ? ? ? ? ? ? ? ? ? //不顯示分吞鸭、秒時的字段
? jumpIssue: true? ? ? ? ? ? ? ? ? ? ? ? ? //是否允許跳期(在render中使用)
};
var?req= function(url1, url2){? ? //計算請求次數(shù)的函數(shù)
?reqParam.count++;
? if(reqParam.count?>=?reqParam.max[reqParam.index]){? //請求次數(shù)到達限定次數(shù)寺董,此間隔結束
? ? clearInterval(reqParam.timer);
? ?requestData(url1, url2);? ? ? ?//清理定時器之后,立即請求一次(本輪的最后一次)
? ? console.log("請求數(shù)組的當前下標:"+reqParam.index+"\n"+
? ? "當前請求次數(shù):"+reqParam.count+"\n"+"當前間隔時間:"+reqParam.arr[reqParam.index]);
? ? reqParam.index++;
? ? if(!reqParam.arr[reqParam.index]) return;? //reqParam.arr中的請求完畢后刻剥,不再進行請求
? ?reqParam.count?= 0;
? ?reqParam.timer= setInterval(function(){? //清除周期性定時器后遮咖,需要重新調用
? ? ?req(url1, url2);? ? ? ? ? ? ? ? ? ? ? ? //回調自己,進行請求
? ? }, reqParam.arr[reqParam.index]);
? }else{
? ?requestData(url1, url2);? ? ? ? //只在此處和階段循環(huán)結束時請求數(shù)據(jù)
? ? console.log("請求數(shù)組的當前下標:"+reqParam.index+"\n"+
? ? "當前請求次數(shù):"+reqParam.count+"\n"+"當前間隔時間:"+reqParam.arr[reqParam.index]);
? }
}
function?requestData(url1, url2){? ? //url1: 獲取多期造虏,url2: 獲取一期
? $.ajax({
? ? url: url1,
? ? data: window.param,? ? ? ? //傳入相應請求參數(shù)
? ? dataType: reqParam.ajaxType,
? ? jsonp: reqParam.jsonp,
? ? success: function(res){
? ? ? if(typeof res !== 'object'){
? ? ? ? res = $.parseJSON(res);
? ? ? }
? ? ? var countTimes = res.data.issueTime.recentDrawTime;? ? //倒計時
? ? ? if(countTimes < 0?&& window.param.num === 1)
? ? ? ? return false;? ? ? ? ? ? ? //后續(xù)請求時御吞,請求到的倒計時小于0,相當于沒請求成功
? ? ?clearInterval(reqParam.timer);? ? ?//請求成功后漓藕,需要第一時間清除定時器
? ? ? reqParam.index = 0;
? ? ? reqParam.count = 0;
? ? ? varrand= 1000;? ? ? ? ? ? ? ? ? ? //用于隨機數(shù)
? ? ? if(typeof render === 'function'){? ?//渲染數(shù)據(jù)(并在其中防止數(shù)據(jù)重復)
? ? ? ?render(res.data);
? ? ? }
? ? ?reqParam.countTimer= setInterval(function(){
? ? ? ? countTimes--; ? ? ? ? ? ? ? ? ?? //每秒減1進行倒計時
? ? ? if(countTimes > 0){
if(reqParam.countdown){
? ? ? ? ? var minute = parseInt(countTimes / 60);
? ? ? ? ? var seconds = parseInt(countTimes % 60);
? ? ? ? ? minute = minute >= 10 ? minute : '0' + minute;
? ? ? ? ? seconds = seconds >= 10 ? seconds : '0' + seconds;
? ? ? ? ? $('#timing').text(minute+':'+seconds);
? ? ? ? }
? ? ? }elseif(countTimes <= 0){
? ? ? ? ? clearInterval(reqParam.countTimer);? ? ? ? ? //倒計時結束陶珠,清除定時器
? ? ? ? ? $('#timing').text(reqParam.desc);
? ? ? ? ?rand*= parseInt(Math.random()*(10 + 1));? ? ?//隨機0-10秒
? ? ? ? ?rand+= res.data.issueTime.queryTime*1000;? ? //倒計時完畢后的查詢時間
? ? ? ? ? setTimeout(function(){
? ? ? ? ? ? console.log('隨機和查詢共:'+rand/1000+'秒');
? ? ? ? ? ? if(window.param.num){
? ? ? ? ? ? ? window.param.num = 1;? ?//當url1和url2相同時,修改window.param里的參數(shù)即可
? ? ? ? ? ? }
? ? ? ? ? ?req(url2, url2);? ? ? ? ? ?//請求一次成功后撵术,將url1替換為url2
? ? ? ? ? },?rand)
? ? ? ?}
? ? ?}, 1000)
? ? }
? })
}
$(function(){
?requestData(url1, url2);? ? //第一次請求數(shù)據(jù)不用定時器背率,所有js加載完畢后開始請求
})
什么是: 讓程序每隔一段時間間隔反復執(zhí)行一項任務(可在定時器中改變某個變量)
何時: 只要讓程序每隔一段時間間隔反復執(zhí)行一項任務
如何: 3件事:
1.任務函數(shù): function task(){...}
?? 定義了定時器每次要執(zhí)行的任務,可用if判斷臨界值,執(zhí)行操作(如停止定時器)
? ? ?停止當前定時器要把函數(shù)放在定時器內寝姿,不能單獨定義
2.啟動定時器: var timer=setInterval(task,間隔(ms))? ? //不要多次聲明(var),可以直接用(=)
?? 強調:task是回調交排,不用加(),要傳參數(shù)時可以把要執(zhí)行的函數(shù)放在回調函數(shù)內
?? 其中: timer是定時器在內存中唯一標識的一個整數(shù)序號(從1開始)
? ?何時: 只要一個定時器可能被停止饵筑,都要在啟動時先保存序號(var timer=...)
3.停止定時器: clearInterval(timer)
? ?其中: timer是要停止的定時器序號
?? 問題: 停止定時器不會自動清空timer變量中的序號埃篓,有可能影響下次啟動
?? 解決: 建議先停止定時器時,再手動清空timer(timer=null)
2種方式:① 手動停止: 用戶通過操作來停止定時器(用timer!=null判斷啟動/停止)
? ? ? ? ② 自動停止:?在任務函數(shù)內反復判斷臨界值
? ? ? ? ? ? ? ? ? ?? 只要達到臨界值根资,就自動停止定時器
一次性定時器:
什么是: 讓程序先等待一段時間架专,再自動執(zhí)行一次任務,執(zhí)行一次后自動停止
何時: 只要讓程序先等待一段時間玄帕,再自動執(zhí)行一次任務
如何: 3件事:?1. 任務函數(shù): ? function task(){...}
? ? ? ? ? ? ?2. 啟動定時器:var timer=setTimeout(task,等待ms)
? ? ? ? ? ? ?3. 停止定時器:clearTimeout(timer);
? ? ? ? ? ? ? ? ? ? ? ? ?? 用于在任務執(zhí)行前部脚,取消等待,不再執(zhí)行
window.onload: 當頁面中所有內容(html,css,js)都加載完裤纹,才自動觸發(fā)onload事件
原理: 定時器中的回調函數(shù)(task)只能在主程序所有語句執(zhí)行完才能開始執(zhí)行
筆試:
var a=10;
setTimeout(function(){console.log(a);},0); ?//先算a++委刘,再輸出11
a++;
注意:js中所有的異步回調函數(shù)(如定時器、ajax)都在正常代碼(非異步代碼)執(zhí)行完之后才執(zhí)行
原因: JavaScript是單線程執(zhí)行的
注意:① 定時器有一個最小執(zhí)行時間鹰椒,IE8及以下最小15.6ms锡移,其它最少4ms
? ? ?② 定時器中的this默認指向window,可使用bind()改變回調函數(shù)中的this
? ? ?③ 定時器的第3漆际、4...個參數(shù)表示第一個參數(shù)(回調函數(shù))傳入的參數(shù)
? ? ?④ 微信內置瀏覽器中淆珊,等待時間為0時,定時器可能會失效奸汇,建議改為10ms