chapter 6、JS----从入门到熟练的小白之路(持续更新....)

273 阅读4分钟

一、验证码案例

【1.1 】 生成有字母、数字组合成的四位验证码

//随机验证码:数字和字母组合,(四个数字和字母)
/* 
===> 1先把验证码准备好
===> 2随机获取相应的索引值
===> 3获取元素
*/
function  getCode(){
    var str="qwertyuiopasdfghjklzxcvbnm"+"QWERTYUIOPASDFGHJKLZXCVBNM"+"0123456789";
    var result="";
    //==> 索引值的范围:0---61
    for(var i=0;i<4;i++){
       var index=Math.round(Math.random()*61);
       var item=str[index];
       result+=item;
    }
    return result;
}
var code=document.getElementById("code");
var btn=document.getElementById("btn");
code.innerHTML=getCode();
btn.onclick=function(){
    code.innerHTML=getCode();
}

【1.2】生成不重复的验证码

for(var i=0;i<4;i++){
       var index=Math.round(Math.random()*61);
       var item=str[index];
       //===>新增一个判断
       if(str.indexOf(item)>-1){
          // 此次循环作废,总共四次,浪费了一次,所以需要
          i--;
          continue;
       }
       result+=item;
    }

【1.3】 while 循环实现

只要条件成立,就一直执行,知道条件不成立的时候停止

while(条件){ 执行体 }

function  getCode(){
    var str="qwertyuiopasdfghjklzxcvbnm"+"QWERTYUIOPASDFGHJKLZXCVBNM"+"0123456789";
    var result="";
    //==> 索引值的范围:0---61
    while(result.length<4){
       var index=Math.round(Math.random()*61);
       var item=str[index];
       if(result.indexOf(item)==-1){
          result+=item;
       }
    }
    return result;
}

二、dom操作

2.1【dom树】:浏览器在加载页面的时候,首先就是dom的结构计算,它形式就像是一颗大树,有很多的分支,所以被称为 "dom tree"

【回流和重绘】

  • 重绘(repaint):当元素样式的改变不影响布局时,浏览器将使用重绘对元素进行更新,此时由于只需要 UI 层面的重新像素绘制,因此损耗较少。

    常见的重绘操作有:

      1. 改变元素颜色
      1. 改变元素背景色
      1. more ……
  • 回流(reflow):又叫重排(layout)。当元素的尺寸、结构或者触发某些属性时,浏览器会重新渲染页面,称为回流。此时,浏览器需要重新经过计算,计算后还需要重新页面布局,因此是较重的操作。

    常见的回流操作有:

      1. 页面初次渲染
      1. 浏览器窗口大小改变
      1. 元素尺寸/位置/内容发生改变
      1. 元素字体大小变化
      1. 添加或者删除可见的 DOM 元素
      1. 激活 CSS 伪类(:hover……)
      1. more …… • 重点:回流必定会触发重绘,重绘不一定会触发回流。重绘的开销较小,回流的代价较高。

2.2[常用的dom操作方法]

1)getElementById:通过元素的id获取元素.

document.getElementById("box");
【document】:
     document 是上下文,限制范围的意思:在哪个范围下的 id名字是box的这个元素,不过这个上下文只能是   document
     
【id名字唯一性】:
     id名字是唯一的,一个document文档中不能同时出现多个相同的id名字,如果设置了多个相同的id,只能获取到第一个。
     
[兼容性注意]:不要让name 和id的名字一样。因为在ie6-ie7 的时候,如果设置了name属性,通过id也可以获取到
<body>
   <input type="text" name="text">
</body>
</html>
<script>
  console.log(document.getElementById("text"));
  //  在ie6或者ie7的时候可以获取到
</script>

2)【context].getElementsByTagName:在特定的上下文中,通过标签名,获取一组元素。

  • 得到的是一个类数组,不能直接用数组的方法
  • 得到的是一个集合,如果想要操作其中的某一项,可以基于索引获取。
    var omain=document.getElementById("main");
    var olis=omain.getElementsByTagName("li");

// 想要获取到第二个li:olis[1]

3) [context].getElementsByCalssName:通过类名获取元素集合

• 此方法在ie6--ie8下不兼容

4)document.getElementsByName:通过name名字获取一组元素集合

  • 它的上下文也只能是document
  • 另外,正常的规范中,咱们只会给表单元素起name值,如果给其它元素设置name,在ie9以下版本浏览器不兼容,是获取不到的,所以为了这种情况,咱们以后养成习惯,只给表单元素用name,非表单元素不用name

5)【context].querySelector("选择器")

通过选择器获取指定的元素,即使匹配的有多个,也只会对第一个起作用,获取到的是一个对象(给咱们平时写样式时候写选择器是一样的)

 <div class="main">
        <div class="box1"></div>
    </div>
    
    document.querySlector(".main>div")

6)【context】.querySelectorAll("选择器")

通过指定的选择器获取一组节点结合 注意:querySelector 和querySelector 在ie6-ie8 下不兼容

7)document.head

获取Head元素对象

8) document.body

获取body元素对象

9) document.documentElement

获取html元素对象

【需求:】获取一屏幕的宽度或者高度,兼容所有的浏览器

// 获取一屏幕的高度
var vH=document.documnentElement.clientHeight || document.body.clientHeight;
// 偶去一屏幕的宽度
var vW=document.documentElement.clientWidth || document.body.clientWidth;

2.3 练习题:

获取页面中所有name属性值为 "hehe" 的元素标签

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
       
    </style>
</head>
<body>
    
   <div class="box1">
       <input type="text" name="he1">
   </div>
   <input class="box1" name="he1">
</body>
</html>
<script>
 function getElementsByName(value){
     var allTag=document.getElementsByTagName("*");
     var names=[];
     for(var i=0;i<allTag.length;i++){
          var item=allTag[i];
          if(item.name==value){
             names.push(item);
          }
     }
     return names;
 }
 var ary=getElementsByName("he1")
</script>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="main">
        <div class="box1">
            <input type="text" name="he1" id="input1">
            <div name="he1" id="div2">111</div>
        </div>
        <input class="box1" name="he1">
    </div>
</body>
</html>
<script>
 var omain=document.getElementById("main");   
 function getName(contex,name,attr){
    var tags=contex.getElementsByTagName("*");
    var ary=[];
    for(var i=0;i<tags.length;i++){
        if(tags[i].getAttribute(name)==attr){
           ary.push(tags[i])
        }
    }
    return ary;
 }
 var res=getName(omain,"name","he1");
 console.log(res);
</script>

关于id的一些鲜为人知的事情: 直接把id当成变量去用的时候,可以获取相应的id元素。(浏览器的机制)

   console.log(box1)

2.4【节点】

1)、文档节点

  • nodeType:9

  • nodeName:"#document"

  • nodeValue:null document.nodeType;

    document.nodeName

    document.nodeValue;

2)、属性节点

  • nodeType:2
  • nodeName:属性名
  • nodeValue:属性值
 <a href="http://www.baidu.com" id="a1">百度</a>
var a1=a1.getAttributeNode("href");// 获取属性节点
console.log(a1.nodeType);//2
console.log(a1.nodeName);//"href"; 属性名
console.log(a1.nodeValue);//"http://www.baidu.com"; 属性值

3)、元素节点

  • nodeType:1
  • nodeName:大写的标签名
  • nodeValue:null

4)、文本节点

  • nodeType:3
  • nodeName:"#text"
  • nodeValue:文本内容
  • 在标准浏览器中,换行和空格也属于文本节点
<a href="http://www.baidu.com" id="a1">百度</a>
var res=a1.childNodes[0];
console.log(res.nodeType);//3
console.log(res.nodeValue);//"百度";
console.log(res.nodeName);//"#text";

5)、注释节点

  • nodeType:8
  • nodeName:"#comment"
  • nodeValue:注释的内容
 <a href="http://www.baidu.com" id="a1">
    <!--a标签 -->
    百度
 </a>
a1.childNodes; //NodeList(3) [text, comment, text]
a1.childNodes[1].nodeName;//"#comment"
a1.childNodes[1].nodeType;//8
a1.childNodes[1].nodeValue;//"a标签 "

2.5【节点的关系关系属性】

1)parentNode

获取当前节点唯一的父亲节点

2)childNodes

获取当前节点所有的子节点

<ul id="main">
       <!-- 我是注释 -->
       <li>你永远是最胖的</li>
       <li>你永远是最胖的</li>
       <li>你永远是最胖的</li>
       <li>你永远是最胖的</li>
</ul>
<script>
console.log(main.childNodes);
</script>

3)children

获取当前元素所有的元素子节点,但是在ie6--ie8下不兼容

console.log(main.children);

4)previousSibling

获取上一个哥哥节点 main.previousSibling

5)previousElementSibling

ie6-ie8 不兼容

<span>1</span>
   <ul id="main">
       <!-- 我是注释 -->
       <li>你永远是最胖的</li>
       <li>你永远是最胖的</li>
       <li>你永远是最胖的</li>
       <li>你永远是最胖的</li>
   </ul>
 <script>
 console.log(main.previousElementSibling);
 //<span>1</span>
 
 <script>

6)nextSibling

获取当前节点的下一个兄弟节点

 <span id="span1">1</span>
   <ul id="main">
       <!-- 我是注释 -->
       <li>你永远是最胖的</li>
       <li>你永远是最胖的</li>
       <li>你永远是最胖的</li>
       <li>你永远是最胖的</li>
   </ul>
   <span>2</span>
   

7) nextElementSibling

获取当前节点的下一个元素兄弟节点 ie6-ie8 不兼容

8)firstChild

获取当前节点的第一个子节点

9)firstElementChild

获取当前节点的第一个元素子节点 ie6-ie8 不兼容

10)lastChild

获取当前节点的最后一个子节点

11) lastElementChild

获取当前节点的最后一个元素子节点 ie6-ie8 不兼容

三、练习题

1) 自己手动封装一个获取节点下面的所有子元素,要求考虑兼容性。

Document </style> 1
  • 选择珠峰的,都是明智的!
  • 选择珠峰的,都是明智的!
  • 选择珠峰的,都是明智的!
  • 选择珠峰的,都是明智的!
2 2) 自己手动封装一个perviousElementSibling,要兼容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
       
    </style>
</head>
<body>
   <span id="span1">1</span>
   <ul id="main">
       <!-- 我是注释 -->
       <li>你永远是最胖的</li>
       <li>你永远是最胖的</li>
       <li>你永远是最胖的</li>
       <li>你永远是最胖的</li>
   </ul>
   <span id="span2">2</span>
</body>
</html>
<script>
 function previousElmentSibling(ele){
     var pre=ele.previousSibling;
     while(pre&&pre.nodeType!==1){
         pre=pre.previousSibling;
     }
     return pre;
 }
 previousElmentSibling(span2)
</script>

四、dom 的增删改

1) createElement:创建一个元素

documment.createElement("div");

2) createTextNode: 创建一个文本节点

var otext=document.createTextNode("哈哈!");

3) appendChild:把元素追加到一个容器的末尾

【context】.appendChild([元素]);

var odiv=documment.createElement("div");
document.body.appendChild(odiv);

4)insertBefore: 把一个元素插入到另一个元素的前面

把新元素添加到原有元素的前面

【context】.insertBefore(newEle,oldEle);

5) cloneNode:把某一个节点进行克隆

  • 【ele】.cloneNode();浅克隆: 只是克隆了一个节点,里面的内容还有样式都没克隆
  • 【ele】.cloneNode(true);深克隆:把节点包含的所有内容进行克隆

6)removeChild:移除某个节点

【context】.removeChild(ele);

7)set/get/removeAttribute

设置/获取/删除 当前元素的某一个自定义属性

  • setAttribute
  • getAttribute
  • removeAttribute
<div id="box"></div>
//=======>  setAttribute  设置
box.setAttribute("index",1);
box.getAttribute("index");
box.removeAttribute("index");
//========> 基于键值对操作
// 设置
box["aa"]=22;
// 获取
box["aa"]
//移除
delete box[aa];

基于键值对方式 增删改:修改当前对象的堆内存空间完成的(在堆内存空间可以看到) 基于Attribute dom方法增删改,是修改html结构来完成的(此种方法设置的在结构上可以看到)

以上两种方式不能混用

五、利用a标签的href来重新获取url参数

var str="www.zhufengpeixun.cn?name=lili&age=18#123" /* search: "?name=lili&age=18" hash: "#123" */

function queryParams(str){
   var a=document.createElement("a");
   a.href=str;
   var obj={};
   console.log(a.search); //?name=lili&age=18
   console.log(a.hash); //#123
   //[name=lili,age=18]
   var search=a.search.substr(1); 
   obj.hash=a.hash?hash:null;
   if(search){
       var searchAry=search.split("&");
       for(var i=0;i<searchAry.length;i++){
             var itemAry=searchAry[i];
             //[name,lili]
             var item=itemAry.split("=");
             var key=item[0];
             var value=item[1];
             obj[key]=value;
       }
   }
   return obj;
}
var dd=queryParams(str);