[toc]
## previously
```
document.getElementById(); //上下文只能是document;只會獲取到一個元素 不用[n]來獲取 id嘛 獨有的
context.getElementByTagName(); //把指令容器中子子孫孫輩分的所有標簽名為TAGNAME的都獲取到了,放在一個數組中
context.getElementsByClassName(CLASSNAME);//同上,但是在IE6~8下不兼容
document.getElementsByName(); //上下文只能是document;在IE瀏覽器中只對表單元素的name起作用
document.body
document.documentElement
context.querySelector/context.querySelectorAll //在IE6~8下不兼容;并且獲取的是static NodeList
```
```
//->描述節點和節點之間關系的屬性(在標準的瀏覽器中會把空格和換行當做文本節點來處理)
childNodes
//->元素節點,不過在IE6~8和標準瀏覽器不一樣,會把注釋加進來?;值獲取兒子;
children
//->Element在IE6~8不兼容
parentNode
previousSibling/previousElementSibling
nextSibling/nextElementSibling
lastChild/lastElementChild
firstChild/firstElementChild
```
```
元素1 文本3 注釋8 document9
```
DOM的增刪改
```
createElement
document.createDocumentFragment()
appendChild
insertBefore
cloneNode(true/false)
replaceChild
removeChild
get/set/removeAttribute
```
DOM盒子模型
```
getComputedStyle
```
## children
獲取某一個容器中的元素子節點(只是兒子)
```
//->首先獲取所有的子節點(childNodes),在所有的子節點中把元素節點過濾出來(nodeType === 1)
function children(curEle,tagName){
var ary = [];
if(/MSIE(6|7|8)/i.test(navigator.userAgent)){
var nodeList = curEle.childNodes; //var連寫時一般讓短的在前面
for(var i=0,len=nodeList.length;i<len;++i){
if(curNode.nodeType===1){
ary[ary.length] = curNode;
}
}
}else{
//children下獲取到的是一個類數組,是一個對象,So要轉換為數組
ary = Array.prototype.slice.call(curEle.children);
}
//->二次篩選
if(typeof tagName === 'string'){
for(var k=0;k<ary.length;++k){ //需要使用.length作為動態的邊界判斷
var curEleNode = ary[k];
if(curEleNode.nodeName.toLowerCase===tagName.toLowerCase()){
ary.splice(k,1);
k--; //因為刪除了,后面的會上移
}
}
}
return ary;
}
console.log(children(oDiv));
```
## prev
```
//prev:獲取上一個哥哥元素節點
//首先獲取當前元素的上一個哥哥節點,判斷是否為元素節點,不是的話基于當前的繼續找上面的哥哥節點...一直找到哥哥元素節點為止,如果沒有哥哥元素界定啊,返回null即可
function prev(curEle){
if(flag){ //如果是標準瀏覽器
return curEle.previousElementSibling;
}
var pre = curEle.previousSibling;
while(pre&&pre.nodeType!==1){
pre = pre.previousSibling;
}
return pre;
}
```
## next
```
function next(curEle){
if(flag){
return curEle.nextElementSibling;
}
var next = curEle.nextSibling;
while(next&&next.nodeType==1){
next = next.nextSibling;
}
return next;
}
```
## prevAll
```
function prevAll(curEle){
var ary = [];
var pre = this.prev(curEle);
while(pre){
ary.unshift(pre);
pre = this.prev(pre);
}
return ary;
}
```
## nextAll
```
function nextAll(curEle){
var ary = [];
var next = this.next(curEle);
while(pre){
ary.push(next);
next = this.next(next);
}
return ary;
}
```
## sibling
獲取相鄰的兩個元素節點
```
function sibling(curEle){
var pre = this.prev(curEle);
var nex = this.next(curEle);
var ary = [];
pre?ary.push(pre):null;
nex?ary.push(nex):null;
return ary;
}
```
## siblings
獲取所有的兄弟元素節點
```
function siblings(curEle){
return this.prevAll(curEle).concat(this.nextAll(curEle));
}
```
## index
獲取當前元素的索引
```
function index(curEle){
return this.prevAll(curEle).length;
}
```
## firstChild和lastChild
```
function firstChild(curEle){
var chs = this.children(curEle); //所有子節點
return this.length>0?chs[0]:null;
}
//->lastChild:獲取最后一個元素子節點
function lastChild(curEle){
var chs = this.children(curEle); //所有子節點
return this.length>0?chs[chs.length-1]:null;
}
```
## append
```
function append(newEle,container){
container.appendChild(newEle);
}
```
## prepend
把新的元素添加到容器中的第一個子元素節點的前面
```
function prepend(newEle,container){
var fir = this.firstChild(container);
if(fir){
container.insertBefore(newEle,fir);
return;
}
container.appendChild(newEle)
}
```
## insertBefore
把新元素追加到指定元素的前面
```
function insertBefore(newEle,oldEle){
oldEle.parentNode.insertBefore(newEle,oldEle);
}
```
## insertAfter
把新的元素追加到指定元素的后面
```
function insertAfter(newEle,oldEle){
var nex = this.next(oldEle);
if(nex){
oldEle.parentNode.insertBefore(newEle,nex);
return;
}
oldEle.parentNode.appendChild(newEle);
}
```
## hasClass
```
//->hasClass:驗證當前元素中是否包含className這個樣式類名
function hasClass(curEle,className){
//curEle.className //->"box bg border"
//->"bg" /\s+bg\s+/
//->"box" /^box\s+/
//->"border" /\s+border$/
var reg = new RegExp("(^| +)"+className+"( +|$)");
return reg.test(curEle.className);
}
console.log(hasClass(box,"bg"));
console.log(hasClass(box,"position"));
```
## addClass
```
function addClass(curEle,className){
if(!hasClass(curEle,className)){
curEle.className += " "+className;
}
}
addClass(box,'position');
```
但這么寫仍然會重復
```
addClass(box,'position bg'); //這么寫仍然會重復
```
以空格拆分為數組,一個一個進行處理
```
function addClass(curEle,className){
//->為了防止className傳遞進來的值包含多個樣式類名,我們把傳遞進來的字符串按照一到多個空格拆分成數組中的每一項
var ary = className.replace(/^ +| +$/g,'').split(/ +/g);
//->循環數組,一項項的進行驗證添加即可
for(var i=0,len=ary.length;i<len;++i){
var curName = ary[i];
if(!hasClass(curEle,curName)){
curEle.className += " "+curName;
}
}
}
```
## removeClass
```
function removeClass(curEle,className){
//->為了防止className傳遞進來的值包含多個樣式類名,我們把傳遞進來的字符串按照一到多個空格拆分成數組中的每一項
var ary = className.replace(/^ +| +$/g,'').split(/ +/g);
//->循環數組,一項項的進行驗證添加即可
for(var i=0,len=ary.length;i<len;++i){
var curName = ary[i];
if(!hasClass(curEle,curName)){
var reg =new RegExp("(^| +)"+curName+"( +|$)");
curEle.className = curEle.className.replace(reg," ");
}
}
}
```
## getElementsByClassName
- 只要包含傳入的類名就會被選中
- 若果傳入的字符串中包含多個類名,那么是選中包含所有這些類名的元素(和傳入字符串中的這些個類名的空格多少與先后順序沒有關系)
- 若沒有匹配中的,則返回空集合
```
//->getElementsByClass:通過元素的樣式類名獲取一組元素集合
//->className:要獲取的樣式類名(可能是一個也可能是多個)
//->獲取元素的上下文->如果這個值不傳遞的話,默認應該是document
function getElementsBycClass(className,context){
conext = context||document;
var classNameAry = className.replace(/^ +| +$/g,'').split(/ +/g); //先去掉首尾空格,然后再按照中間的空格把它里面的每一項拆分成數組
var ary = [];
//->獲取指定的上下文中所有的元素標簽,循環這些標簽,獲取每一個標簽的className樣式類名的字符串
var nodeList = context.getElementsByTagName("*"); //->獲取指定上下文中的所有的元素標簽
for(var i=0,len=nodeList.length;i<len;++i){
var curNode = nodeList[i];
//->判斷curNode.className是否即包含"w3"也包含"w1" ,如果兩個都包含的話,curNode就是我想要的,否則就不是我想要的
var isOk = true;//->我們假設curNode中包含了所有的樣式
for(var k=0;k<classNameAry.length;++k){
var reg = new RegExp("(^| +)+curNameAry[k]+( +|$)")
if(!reg.test(curNode.className)){
isOk = false;
break;
}
}
if(isOk){ //拿每一個標簽分別和所有樣式類名比較后,如果結果還是true的話,說明當前元素標簽包含了所有的樣式,也是我們想要的
ary.push(curNode);
}
}
return ary;
}
console.log(getElementsByClass("w3 w1 "));
```
## setCss
在JS中給元素設置樣式屬性值,我們只能通過`curEle.style[attr]=value`這種方式給當前元素設置行內樣式
setCss給當前元素的某一個樣式屬性設置值(增加在行內樣式上的)
```
function setCss(curEle,attr,value){
//->在JS中設置float樣式值的話也需要處理兼容
if(attr==="float"){
curEle['style']['cssFloat'] = value;
curEle['style']['styleFloat'] = value;
return;
}
//->如果打算設置的是元素的透明度,我們需要設置兩套樣式來兼容所有的瀏覽器
if(attr === 'opacity'){
curEle['style']['opacity'] = value;
curEle['style']['filter'] = "alpha(opacity="+value*100+")";
return;
}
// ->對于某些樣式屬性,如果傳遞進來的值沒有加單位,我們需要把單位默認的補充上,這樣的話,這個方法就會人性化一些
var reg = null;
reg = /^(width|height|top|bottom|left|right|((margin|padding)(Top|Bottom|Left|Right)?))$/;
if(reg.test(attr)){
if(!isNaN(value)){ //如果為true,說明加單位了
value+='px';
}
}
curEle['style'][attr] = value;
}
setCss(box,'left','100px');
setCss(box,'left',200);
setCss(box,'background',"red");
setCss(box,"opacity",0.1);
setCss(box,"borderTop","10px solid #000");
setCss(box,"padding","10px 20px 30px 40px");
setCss(box,"padding",10); //復合值的話 只支持4個值都相同的情況下不加單位
```
## setGroupCss
```
function setGroupCss(curEle,options){
//->通過檢測options的數據類型,如果不是一個對象,則不能進行批量的設置
options = options||0; //排除null和undefined
if(Object.prototype.toString.call(options)!=="[object Object]"){
return;
}
for(var key in options){
if(options.hasOwnProperty(key)){
this.setCss(curEle,key,options[key]);
}
}
}
utils.setGroupCss(box,{
width:200
,backgroundColor:"red"
,opacity:0.1
,float:"right"
,borderTop:"10px solid #000"
,padding:10
})
```
## css
此方法實現了獲取、單獨設置、批量設置元素的樣式值
```
function css(curEle){
var argTwo = arguments[1];
if(typeof argTwo === 'string'){ //->第一個參數值是一個字符串,這樣的話很有肯能就是在獲取樣式,為什么說是很有可能呢?因為還需要判斷是否存在第三個參數,如果第三個參數存在的話,就不是獲取了,而是在單獨的設置樣式屬性值
var argThree = arguments[2];
if(!argThree){ //->第三個參數不存在;
// return this.getCss(curEle,argTwo);
return this.getCss.apply(this,arguments);
}
//->第三個參數存在則為單獨設置
// this.setCss(curEle,argTwo,argThree);
this.setCss.apply(this,arguments);
}
argTwo = argTwo || 0;
if(argTwo.toString === "[object Object]"){
//->批量設置樣式屬性值
this.setGroupCss.apply(this.arguments);
}
}
```
其中的`!argThree`有bug,
因為有可能這個值是個0這樣判斷的話就會進來,但并不是死我們所期望的,它本應該是設置值,應該判斷它是不是undefined
```
if(typeof argument[2]==='undefined'){}
```
- 空白目錄
- window
- location
- history
- DOM
- 什么是DOM
- JS盒子模型
- 13個核心屬性
- DOM優化
- 回流與重繪
- 未整理
- 文檔碎片
- DOM映射機制
- DOM庫封裝
- 事件
- 功能組件
- table
- 圖片延遲加載
- 跑馬燈
- 回到頂部
- 選項卡
- 鼠標跟隨
- 放大鏡
- 搜索
- 多級菜單
- 拖拽
- 瀑布流
- 數據類型的核心操作原理
- 變量提升
- 閉包(scope)
- this
- 練習題
- 各種數據類型下的常用方法
- JSON
- 數組
- object
- oop
- 單例模式
- 高級單例模式
- JS中常用的內置類
- 基于面向對象創建數據值
- 原型和原型鏈
- 可枚舉和不可枚舉
- Object.create
- 繼承的六種方式
- ES6下一代js標準
- babel
- 箭頭函數
- 對象
- es6勉強筆記
- 流程控制
- switch
- Ajax
- eval和()括號表達式
- 異常信息捕獲
- 邏輯與和或以及前后自增
- JS中的異步編程思想
- 上云
- 優化技巧
- 跨域與JSONP
- 其它跨域相關問題
- console
- HTML、XHTML、XML
- jQuery
- zepto
- 方法重寫和方法重載
- 移動端
- 響應式布局開發基礎
- 項目一:創意簡歷