• 6、JavaScript进阶篇③——浏览器对象、Dom对象


    一、浏览器对象

    1、 window对象

    window对象是BOM的核心,window对象指当前的浏览器窗口。

    window对象方法:

    注意:在JavaScript基础篇中,已讲解了部分属性,window对象重点讲解计时器

    代码示例:

    <!DOCTYPE HTML>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>window对象</title>
    <script type="text/javascript">
    function show(){
        alert("欢迎来到慕课网!");
        window.open('http://www.imooc.com','_blank');
        }
    </script>
    </head>
    <body>
    <form>
    <input type="button" value="点击我,打开新窗口" onclick="show()" />
    </form>
    </body>
    </html>

    先弹出alert 对话框,然后点击确定就进入新的窗口。

    2、 JavaScript计时器

    在JavaScript中,我们可以在设定的时间间隔之后来执行代码,而不是在函数被调用后立即执行。
    计时器类型:
    一次性计时器:仅在指定的延迟时间之后触发一次。
    间隔性触发计时器:每隔一定的时间间隔就触发一次。
    计时器方法:

     2.1、 计时器setInterval()

    在执行时,从载入页面后每隔指定的时间执行代码。

    语法:

    setInterval(代码,交互时间);

    参数说明:

    1. 代码:要调用的函数或要执行的代码串。

    2. 交互时间:周期性执行或调用表达式之间的时间间隔,以毫秒计(1s=1000ms)。

    返回值:

    一个可以传递给 clearInterval() 从而取消对"代码"的周期性执行的值。

    调用函数格式(假设有一个clock()函数):

    setInterval("clock()",1000)
    或
    setInterval(clock,1000)

    我们设置一个计时器,每隔100毫秒调用clock()函数,并将时间显示出来,代码如下:

    <!DOCTYPE HTML>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>计时器</title>
    <script type="text/javascript">
      var int=setInterval(clock, 100)
      function clock(){
        var time=new Date();
        document.getElementById("clock").value = time;
      }
    </script>
    </head>
    <body>
      <form>
        <input type="text" id="clock" size="50"  />
      </form>
    </body>
    </html>

     代码练习:

     1 <!DOCTYPE HTML>
     2 <html>
     3 <head>
     4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     5 <title>定时器</title>
     6 <script type="text/javascript">
     7   var attime;
     8   function clock(){
     9     var time=new Date();
    10     var HH=time.getHours();
    11     var mm=time.getMinutes();
    12     var ss=time.getSeconds();
    13     attime=HH+":"+mm+":"+ss ;
    14     document.getElementById("clock").value = attime;
    15   }
    16     setInterval(clock,1000);
    17   
    18 </script>
    19 </head>
    20 <body>
    21 <form>
    22 <input type="text" id="clock" size="50"  style="background:#000;color:#00ff00;50px;" />
    23 </form>
    24 </body>
    25 </html>

    结果:

    2.2、 取消计时器clearInterval()

    clearInterval() 方法可取消由 setInterval() 设置的交互时间。

    语法:

    clearInterval(id_of_setInterval)

    参数说明:
    id_of_setInterval:由 setInterval() 返回的 ID 值。

    每隔 100 毫秒调用 clock() 函数,并显示时间。当点击按钮时,停止时间,代码如下:

    <!DOCTYPE HTML>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>计时器</title>
    <script type="text/javascript">
       function clock(){
          var time=new Date();                     
          document.getElementById("clock").value = time;
       }
    // 每隔100毫秒调用clock函数,并将返回值赋值给i
         var i=setInterval("clock()",100);
    </script>
    </head>
    <body>
      <form>
        <input type="text" id="clock" size="50"  />
        <input type="button" value="Stop" onclick="clearInterval(i)"  />
      </form>
    </body>
    </html>

     2.3、 计时器setTimeout()

    setTimeout()计时器,在载入后延迟指定时间后,去执行一次表达式,仅执行一次。

    语法:

    setTimeout(代码,延迟时间);

    参数说明:

    1. 要调用的函数或要执行的代码串。
    2. 延时时间:在执行代码前需等待的时间,以毫秒为单位(1s=1000ms)。

    当我们打开网页3秒后,在弹出一个提示框,代码如下:

    <!DOCTYPE HTML>
    <html>
    <head>
    <script type="text/javascript">
      setTimeout("alert('Hello!')", 3000 );
    </script>
    </head>
    <body>
    </body>
    </html>

    当按钮start被点击时,setTimeout()调用函数,在5秒后弹出一个提示框。

    <!DOCTYPE HTML>
    <html>
    <head>
    <script type="text/javascript">
    function tinfo(){
      var t=setTimeout("alert('Hello!')",5000);
     }
    </script>
    </head>
    <body>
    <form>
      <input type="button" value="start" onClick="tinfo()">
    </form>
    </body>
    </html>

    要创建一个运行于无穷循环中的计数器,我们需要编写一个函数来调用其自身。在下面的代码,当按钮被点击后,输入域便从0开始计数。

    <!DOCTYPE HTML>
    <html>
    <head>
    <script type="text/javascript">
    var num=0;
    function numCount(){
     document.getElementById('txt').value=num;
     num=num+1;
     setTimeout("numCount()",1000);
     }
    </script>
    </head>
    <body>
    <form>
    <input type="text" id="txt" />
    <input type="button" value="Start" onClick="numCount()" />
    </form>
    </body>
    </html>

     代码示例:

     1 <!DOCTYPE HTML>
     2 <html>
     3 <head>
     4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     5 <title>计时器</title>
     6 </head>
     7 <script type="text/javascript">
     8   var num=0;
     9   function startCount() {
    10     document.getElementById('count').value=num;
    11     num=num+1;
    12     setTimeout("startCount()",1000);
    13   }
    14   
    15 </script>
    16 </head>
    17 <body>
    18 <form>
    19 <input type="text" id="count" onclick="startCount()"/>
    20 </form>
    21 </body>
    22 </html>

    结果:

     2.4、 取消计时器clearTimeout()

    setTimeout()和clearTimeout()一起使用,停止计时器。

    语法:

    clearTimeout(id_of_setTimeout)

    参数说明:
    id_of_setTimeout:由 setTimeout() 返回的 ID 值。该值标识要取消的延迟执行代码块。

    下面的例子和上节的无穷循环的例子相似。唯一不同是,现在我们添加了一个 "Stop" 按钮来停止这个计数器:

    <!DOCTYPE HTML>
    <html>
    <head>
    <script type="text/javascript">
      var num=0,i;
      function timedCount(){
        document.getElementById('txt').value=num;
        num=num+1;
        i=setTimeout(timedCount,1000);
      }
        setTimeout(timedCount,1000);
      function stopCount(){
        clearTimeout(i);
      }
    </script>
    </head>
    <body>
      <form>
        <input type="text" id="txt">
        <input type="button" value="Stop" onClick="stopCount()">
      </form>
    </body>
    </html>

     代码示例:

     1 <!DOCTYPE HTML>
     2 <html>
     3 <head>
     4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     5 <title>计时器</title>
     6 </head>
     7 <script type="text/javascript">
     8   var num=0;
     9   var i;
    10   function startCount(){
    11     document.getElementById('count').value=num;
    12     num=num+1;
    13     i=setTimeout("startCount()",100);
    14   }
    15   function stopCount(){
    16     clearTimeout(i);
    17   }
    18 </script>
    19 </head>
    20 <body>
    21   <form>
    22     <input type="text" id="count" />
    23     <input type="button" value="Start"  onclick="startCount()"/>
    24     <input type="button" value="Stop"   onclick="stopCount()"/>
    25   </form>
    26 </body>
    27 </html>

    结果:

    3、 History 对象

    history对象记录了用户曾经浏览过的页面(URL),并可以实现浏览器前进与后退相似导航的功能。

    注意:从窗口被打开的那一刻开始记录,每个浏览器窗口、每个标签页乃至每个框架,都有自己的history对象与特定的window对象关联。

    语法:

    window.history.[属性|方法]

    注意:window可以省略。

    History 对象属性

    History 对象方法

    使用length属性,当前窗口的浏览历史总长度,代码如下:

    <script type="text/javascript">
      var HL = window.history.length;
      document.write(HL);
    </script>

     3.1、 返回前一个浏览的页面 back()

    back()方法,加载 history 列表中的前一个 URL。

    语法:

    window.history.back();

    比如,返回前一个浏览的页面,代码如下:

    window.history.back();

    注意:等同于点击浏览器的倒退按钮。

    back()相当于go(-1),代码如下:

    window.history.go(-1);

    3.2、 返回下一个浏览的页面 forward()

    forward()方法,加载 history 列表中的下一个 URL。

    如果倒退之后,再想回到倒退之前浏览的页面,则可以使用forward()方法,代码如下:

    window.history.forward();

    注意:等价点击前进按钮。

    forward()相当于go(1),代码如下:

    window.history.go(1);

    3.3、 返回浏览历史中的其他页面 go()

    go()方法,根据当前所处的页面,加载 history 列表中的某个具体的页面。

    语法:

    window.history.go(number);

    参数:

    浏览器中,返回当前页面之前浏览过的第二个历史页面,代码如下:

    window.history.go(-2);

    注意:和在浏览器中单击两次后退按钮操作一样。

    同理,返回当前页面之后浏览过的第三个历史页面,代码如下:

    window.history.go(3);

    4、 location对象

    location用于获取或设置窗体的URL,并且可以用于解析URL。

    语法:

    location.[属性|方法]

    location对象属性图示:

    location 对象属性:

    location 对象方法:

    5、 navigator对象

    Navigator 对象包含有关浏览器的信息,通常用于检测浏览器与操作系统的版本。

    对象属性:

    查看浏览器的名称和版本,代码如下:

    <script type="text/javascript">
       var browser=navigator.appName;
       var b_version=navigator.appVersion;
       document.write("Browser name"+browser);
       document.write("<br>");
       document.write("Browser version"+b_version);
    </script>

    5.1、 userAgent属性

    返回用户代理头的字符串表示(就是包括浏览器版本信息等的字符串)

    语法

    navigator.userAgent

    几种浏览的user_agent.,像360的兼容模式用的是IE、极速模式用的是chrom的内核。

    使用userAgent判断使用的是什么浏览器(假设使用的是IE8浏览器),代码如下:

    function validB(){ 
      var u_agent = navigator.userAgent; 
      var B_name="Failed to identify the browser"; 
      if(u_agent.indexOf("Firefox")>-1){ 
          B_name="Firefox"; 
      }else if(u_agent.indexOf("Chrome")>-1){ 
          B_name="Chrome"; 
      }else if(u_agent.indexOf("MSIE")>-1&&u_agent.indexOf("Trident")>-1){ 
          B_name="IE(8-10)";  
      }
        document.write("B_name:"+B_name+"<br>");
        document.write("u_agent:"+u_agent+"<br>"); 
    } 

    运行结果:

     6、 screen对象

    screen对象用于获取用户的屏幕信息。

    语法:

    window.screen.属性

    对象属性:

    6.1、 屏幕分辨率的高和宽

    window.screen 对象包含有关用户屏幕的信息。
    1. screen.height 返回屏幕分辨率的高
    2. screen.width 返回屏幕分辨率的宽
    注意:
    1.单位以像素计。
    2. window.screen 对象在编写时可以不使用 window 这个前缀。
    我们来获取屏幕的高和宽,代码如下:

    <script type="text/javascript">
      document.write( "屏幕宽度:"+screen.width+"px<br />" );
      document.write( "屏幕高度:"+screen.height+"px<br />" );
    </script>

     6.2、 屏幕可用高和宽度

    1. screen.availWidth 属性返回访问者屏幕的宽度,以像素计,减去界面特性,比如任务栏。

    2. screen.availHeight 属性返回访问者屏幕的高度,以像素计,减去界面特性,比如任务栏。

    注意:

    不同系统的任务栏默认高度不一样,及任务栏的位置可在屏幕上下左右任何位置,所以有可能可用宽度和高度不一样。

    我们来获取屏幕的可用高和宽度,代码如下:

    <script type="text/javascript">
    document.write("可用宽度:" + screen.availWidth);
    document.write("可用高度:" + screen.availHeight);
    </script>

    注意:根据屏幕的不同显示值不同。

    【编程练习】

    制作一个跳转提示页面:

    要求:

    1. 如果打开该页面后,如果不做任何操作则5秒后自动跳转到一个新的地址,如慕课网主页。

    2. 如果点击“返回”按钮则返回前一个页面。

    效果:

    注意: 在窗口中运行该程序时,该窗口一定要有历史浏览记录,否则"返回"无效果。

    任务:

    第一步: 先编写好网页布局,如下:

       

    第二步: 获取显示秒数的元素,通过定时器来更改秒数。

    第三步: 通过window的location和history对象来控制网页的跳转。

    代码:

     1 <!DOCTYPE html>
     2 <html>
     3  <head>
     4   <title>浏览器对象</title>  
     5   <meta http-equiv="Content-Type" content="text/html; charset=gb2312"/>   
     6  </head>
     7  <body>
     8   <H4>操作成功</H4>
     9   <p>
    10      <b id="second">5</b>秒后回到主页&nbsp;<a href="javascript:goBack();">返回</a>  
    11   </p>
    12  
    13 <script type="text/javascript">  
    14  
    15     var sec = document.getElementById("second");
    16     var i = 5;
    17     var timer = setInterval(function(){
    18         i--;
    19         sec.innerHTML = i;
    20         if(i==1){
    21             window.location.href =  "http://www.imooc.com/";
    22         }
    23     },1000);
    24      
    25   function goBack(){ 
    26     window.history.go(-1);
    27   }  
    28   </script> 
    29  </body>
    30 </html>

    二、 DOM对象,控制HTML元素

    1、 认识DOM

    文档对象模型DOM(Document Object Model)定义访问和处理HTML文档的标准方法。DOM 将HTML文档呈现为带有元素、属性和文本的树结构(节点树)。

    先来看看下面代码:

    将HTML代码分解为DOM节点层次图:

    HTML文档可以说由节点构成的集合,DOM节点有:

    1. 元素节点:上图中<html>、<body>、<p>等都是元素节点,即标签。

    2. 文本节点:向用户展示的内容,如<li>...</li>中的JavaScript、DOM、CSS等文本。

    3. 属性节点:元素属性,如<a>标签的链接属性href="http://www.imooc.com"。

    节点属性:

    遍历节点树:

    以上图ul为例,它的父级节点body,它的子节点3个li,它的兄弟结点h2、P。

    DOM操作:

    注意:前两个是document方法。

     1.1、 getElementsByName() 方法

    返回带有指定名称的节点对象的集合。

    语法:

    document.getElementsByName(name)

    与getElementById() 方法不同的是,通过元素的 name 属性查询元素,而不是通过 id 属性。

    注意:

    1. 因为文档中的 name 属性可能不唯一,所有 getElementsByName() 方法返回的是元素的数组,而不是一个元素。

    2. 和数组类似也有length属性,可以和访问数组一样的方法来访问,从0开始。

    看看下面的代码:

    运行结果:

     1.2、 getElementsByTagName() 方法

    返回带有指定标签名的节点对象的集合。返回元素的顺序是它们在文档中的顺序。

    语法:

    getElementsByTagName(Tagname)

    说明:

    1. Tagname是标签的名称,如p、a、img等标签名。

    2. 和数组类似也有length属性,可以和访问数组一样的方法来访问,所以从0开始。

    看看下面代码,通过getElementsByTagName()获取节点。

    试一试,使用三种获取节点的方法,完成下面的任务:

    在第73行补充代码,通过ID获取标题H1。

    在第78行补充代码,通过name获取值为sex的元素。

    在第84行补充代码,通过标签名获取input元素。

     1 <!DOCTYPE HTML>
     2 <html>  
     3 <head>  
     4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  
     5 <title>JavaScript</title>  
     6 </head>  
     7 <body>  
     8     
     9         <form name="Input">
    10             <table align="center" width="500px" height="50%" border="1">
    11                 <tr>
    12                     <td align="center" width="100px">
    13                         学号:
    14                     </td>
    15                     <td align="center" width="300px">
    16                         <input type="text" id=userid name="user" onblur="validate();">
    17                         <div id=usermsg></div>
    18                     </td>
    19                 </tr>
    20                 <tr>
    21                     <td align="center" width="100px">
    22                         姓名:
    23                     </td>
    24                         <td align="center">
    25                         <input type="text" name="name">
    26                     </td>
    27                 </tr>
    28                 <tr>
    29                     <td align="center" width="%45">
    30                         性别:
    31                     </td>
    32                     <td align="center">
    33                         <input type="radio" name="sex" value="男">
    34 35                         <input type="radio" name="sex" value="女">
    36 37                     </td>
    38                 </tr>
    39                 <tr>
    40                     <td align="center" width="30%">
    41                         年龄:
    42                     </td>
    43                     <td align="center" width="300px">
    44                         <input type="text" name="age">
    45                     </td>
    46                 </tr>
    47                 <tr>
    48                     <td align="center" width="100px">
    49                         地址:
    50                     </td>
    51                     <td align="center" width="300px">
    52                         <input type="text" name="addr">
    53                     </td>
    54                 </tr>
    55 
    56             </table>
    57         </form>
    58         <h1 id="myHead" onclick="getValue()">
    59             看看三种获取节点的方法?
    60         </h1>
    61         <p>
    62             点击标题弹出它的值。
    63         </p>
    64         <input type="button" onclick="getElements()"
    65             value="看看name为sex的节点有几个?" />
    66         <Br>
    67         <input type="button" onclick="getTagElements()"
    68             value="看看标签名为input的节点有几个?" />
    69             
    70      <script type="text/javascript">
    71          function getValue()
    72           {
    73               var myH=document.getElementById("myhead");
    74               alert(myH.innerHTML);
    75           }
    76           function getElements()
    77           {
    78              var myS=document.getElementsByName("sex");
    79               alert(myS.length);
    80           }
    81 
    82           function getTagElements()
    83           {
    84               var myI=document.getElementsByTagName("input");
    85               alert(myI.length);
    86           }
    87          
    88      </script>        
    89 
    90     </body>
    91 </html>

    1.3、 区别getElementByID,getElementsByName,getElementsByTagName

    以人来举例说明,人有能标识身份的身份证,有姓名,有类别(大人、小孩、老人)等。

    1. ID 是一个人的身份证号码,是唯一的。所以通过getElementById获取的是指定的一个人。

    2. Name 是他的名字,可以重复。所以通过getElementsByName获取名字相同的人集合。

    3. TagName可看似某类,getElementsByTagName获取相同类的人集合。如获取小孩这类人,getElementsByTagName("小孩")。

    把上面的例子转换到HTML中,如下:

    <input type="checkbox" name="hobby" id="hobby1">  音乐

    input标签就像人的类别。

    name属性就像人的姓名。

    id属性就像人的身份证。

    方法总结如下:

    注意:方法区分大小写

    通过下面的例子(6个name="hobby"的复选项,两个按钮)来区分三种方法的不同:

      <input type="checkbox" name="hobby" id="hobby1">  音乐
      <input type="checkbox" name="hobby" id="hobby2">  登山
      <input type="checkbox" name="hobby" id="hobby3">  游泳
      <input type="checkbox" name="hobby" id="hobby4">  阅读
      <input type="checkbox" name="hobby" id="hobby5">  打球
      <input type="checkbox" name="hobby" id="hobby6">  跑步 
      <input type="button" value = "全选" id="button1">
      <input type="button" value = "全不选" id="button1">

    1. document.getElementsByTagName("input"),结果为获取所有标签为input的元素,共8个。

    2. document.getElementsByName("hobby"),结果为获取属性name="hobby"的元素,共6个。

    3. document.getElementById("hobby6"),结果为获取属性id="hobby6"的元素,只有一个,"跑步"这个复选项。

     代码练习:

    1.在第27行处补充完整,实现当点击"全选"按钮时,将选中所有的复选项。

    提示:document.getElementsByTagName("input")获取的是所有input标签,包括复选项和按钮,所以要判断是否是复选项,如是选中。

    2.在第33行处补充完整,实现当点击"全不选"按钮时,将取消所有选中的复选项。

    3.在第40行处补充完整,在文本框中输入输入1-6数值,当点击"确定"按钮时,根据输入的数值,通过id选中相应的复选项。

    代码:

     1 <!DOCTYPE HTML>
     2 <html>
     3     <head>
     4         <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
     5         <title>无标题文档</title>
     6     </head>    
     7     <body>
     8         <form>
     9           请选择你爱好:<br>
    10           <input type="checkbox" name="hobby" id="hobby1">  音乐
    11           <input type="checkbox" name="hobby" id="hobby2">  登山
    12           <input type="checkbox" name="hobby" id="hobby3">  游泳
    13           <input type="checkbox" name="hobby" id="hobby4">  阅读
    14           <input type="checkbox" name="hobby" id="hobby5">  打球
    15           <input type="checkbox" name="hobby" id="hobby6">  跑步 <br>
    16           <input type="button" value = "全选" onclick = "checkall();">
    17           <input type="button" value = "全不选" onclick = "clearall();">
    18           <p>请输入您要选择爱好的序号,序号为1-6:</p>
    19           <input id="wb" name="wb" type="text" >
    20           <input name="ok" type="button" value="确定" onclick = "checkone();">
    21         </form>
    22         <script type="text/javascript">
    23         function checkall(){
    24             var hobby = document.getElementsByTagName("input");
    25             for(i = 0;i < hobby.length;i++){
    26                     if(hobby[i].type == "checkbox"){
    27                       hobby[i].checked = true;   }
    28                   }
    29         }
    30         function clearall(){
    31             var hobby = document.getElementsByName("hobby");
    32             for(i = 0;i < hobby.length;i++){
    33                 hobby[i].checked = false;}
    34         }        
    35         function checkone(){
    36             var j=document.getElementById("wb").value;
    37             var hobby = document.getElementById("hobby"+j);
    38             hobby.checked = true;    }        
    39         </script>
    40     </body>
    41 </html>

    结果:

     1.4、 getAttribute()方法

    通过元素节点的属性名称获取属性的值。

    语法:

    elementNode.getAttribute(name)

    说明:

    1. elementNode:使用getElementById()、getElementsByTagName()等方法,获取到的元素节点。

    2. name:要想查询的元素节点的属性名字

    看看下面的代码,获取h1标签的属性值:

    运行结果:

    h1标签的ID :alink
    h1标签的title :getAttribute()获取标签的属值

     代码练习:

     1 <!DOCTYPE HTML>
     2 <html>
     3 <head>
     4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     5 <title>getAttribute()</title>
     6 </head>
     7 <body>   
     8 <p id="intro">课程列表</p>  
     9     <ul>  
    10         <li title="第1个li">HTML</li>  
    11         <li>CSS</li>  
    12         <li title="第3个li">JavaScript</li>  
    13         <li title="第4个li">Jquery</li>  
    14         <li>Html5</li>  
    15     </ul>  
    16 <p>以下为获取的不为空的li标签title值:</p>
    17 <script type="text/javascript">
    18     var con=document.getElementsByTagName("li");
    19     for (var i=0; i< con.length;i++){
    20     var text=con[i].getAttribute("title");
    21       if(text!=null)
    22       {
    23         document.write(text+"<br>");
    24       }
    25     } 
    26  </script> 
    27 </body>
    28 </html>

    1.5、 setAttribute()方法

    setAttribute() 方法增加一个指定名称和值的新属性,或者把一个现有的属性设定为指定的值。

    语法:

    elementNode.setAttribute(name,value)

    说明:

    1.name: 要设置的属性名。

    2.value: 要设置的属性值。

    注意:

    1.把指定的属性设置为指定的值。如果不存在具有指定名称的属性,该方法将创建一个新属性。

    2.类似于getAttribute()方法,setAttribute()方法只能通过元素节点对象调用的函数。

    2、 节点属性

    在文档对象模型 (DOM) 中,每个节点都是一个对象。DOM 节点有三个重要的属性 :

    1. nodeName : 节点的名称

    2. nodeValue :节点的值

    3. nodeType :节点的类型

    一、nodeName 属性: 节点的名称,是只读的。

    1. 元素节点的 nodeName 与标签名相同
    2. 属性节点的 nodeName 是属性的名称
    3. 文本节点的 nodeName 永远是 #text
    4. 文档节点的 nodeName 永远是 #document

    二、nodeValue 属性:节点的值

    1. 元素节点的 nodeValue 是 undefined 或 null
    2. 文本节点的 nodeValue 是文本自身
    3. 属性节点的 nodeValue 是属性的值

    三、nodeType 属性: 节点的类型,是只读的。以下常用的几种结点类型:

    元素类型    节点类型
      元素          1
      属性          2
      文本          3
      注释          8
      文档          9

    代码示例:

    试一试,在<script>的标签内容,获取所有LI标签,并输出相应节点的名称、节点的值、节点的类型。

     1 <!DOCTYPE HTML>
     2 <html>
     3 <head>
     4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     5 <title>节点属性</title>
     6 </head>
     7 <body>
     8   <ul>
     9      <li>javascript</li>
    10      <li>HTML/CSS</li>
    11      <li>jQuery</li>     
    12   </ul>
    13   <script type="text/javascript">
    14     var liArr=document.getElementsByTagName("li");
    15     for(var i=0;i<liArr.length;i++){
    16             document.write(""+i+"个节点的名称:"+liArr[i].nodeName+"<br/>");
    17             document.write(""+i+"个节点的值:"+liArr[i].nodeValue+"<br/>");
    18             document.write(""+i+"个节点的类型:"+liArr[i].nodeType+"<br/>");
    19         }
    20    
    21   </script>
    22 </body>
    23 </html>

    2.1、 访问子节点childNodes

    访问选定元素节点下的所有子节点的列表,返回的值可以看作是一个数组,他具有length属性。

    语法:

    elementNode.childNodes

    注意:

    如果选定的节点没有子节点,则该属性返回不包含节点的 NodeList。

    我们来看看下面的代码:

    运行结果:

    IE:

      UL子节点个数:3
      节点类型:1

    其它浏览器:

       UL子节点个数:7
       节点类型:3

    注意:

    1. IE全系列、firefox、chrome、opera、safari兼容问题

    2. 节点之间的空白符,在firefox、chrome、opera、safari浏览器是文本节点,所以IE是3,其它浏览器是7,如下图所示:

    如果把代码改成这样:

    <ul><li>javascript</li><li>jQuery</li><li>PHP</li></ul>

    运行结果:(IE和其它浏览器结果是一样的)

      UL子节点个数:3
      节点类型:1

    代码示例:

     1 <!DOCTYPE HTML>
     2 <html>
     3 <head>
     4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     5 <title>无标题文档</title>
     6 </head>
     7 <body>
     8 <div>
     9   javascript  
    10   <p>javascript</p>
    11   <div>jQuery</div>
    12   <h5>PHP</h5>
    13 </div>
    14 <script type="text/javascript">
    15  var x=document.getElementsByTagName("div")[0].childNodes;
    16   document.write("第一个div的子节点对应的节点类型分别为:<br/>");
    17  for(var i=0;i<x.length;i++){
    18         document.write(x[i].nodeType+"<br/>");
    19      }
    20 </script>
    21 </body>
    22 </html>

    2.2、 访问子节点的第一项(firstChild)和最后项(lastChild)

    一、firstChild 属性返回‘childNodes’数组的第一个子节点。如果选定的节点没有子节点,则该属性返回 NULL。

    语法:

    node.firstChild

    说明:与elementNode.childNodes[0]是同样的效果。 

    二、 lastChild 属性返回‘childNodes’数组的最后一个子节点。如果选定的节点没有子节点,则该属性返回 NULL。

    语法:

    node.lastChild

    说明:与elementNode.childNodes[elementNode.childNodes.length-1]是同样的效果。 

    注意: 上一节中,我们知道Internet Explorer 会忽略节点之间生成的空白文本节点,而其它浏览器不会。我们可以通过检测节点类型,过滤子节点。 (以后章节讲解)

    代码示例:

    <!DOCTYPE HTML>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>无标题文档</title>
    </head>
    <body>
    <!--调整前-->
    <!--<div id="con">
        <p>javascript</p>
        <div>jQuery</div>
        <h5>PHP</h5>
    </div>-->
    <!--调整后-->
    <div id="con"><p>javascript</p><div>jQuery</div><h5>PHP</h5></div>
    <script type="text/javascript">
      var x=document.getElementById("con");
     document.write(x.firstChild.nodeName+"<br/>");
     document.write(x.lastChild.nodeName+"<br/>");
    </script>
    </body>
    </html>

    结果:

    2.3、 访问父节点parentNode

    获取指定节点的父节点

    语法:

    elementNode.parentNode

    注意:父节点只能有一个。

    看看下面的例子,获取 P 节点的父节点,代码如下:

    <div id="text">
      <p id="con"> parentNode 获取指点节点的父节点</p>
    </div> 
    <script type="text/javascript">
      var mynode= document.getElementById("con");
      document.write(mynode.parentNode.nodeName);
    </script>

    运行结果:

    parentNode 获取指点节点的父节点
    DIV

    访问祖节点:

    elementNode.parentNode.parentNode

    看看下面的代码:

    <div id="text">  
      <p>
        parentNode      
        <span id="con"> 获取指点节点的父节点</span>
      </p>
    </div> 
    <script type="text/javascript">
      var mynode= document.getElementById("con");
      document.write(mynode.parentNode.parentNode.nodeName);
    </script>

    运行结果:

    parentNode获取指点节点的父节点
    DIV

    注意: 浏览器兼容问题,chrome、firefox等浏览器标签之间的空白也算是一个文本节点。

    练习:

    试一试,通过获取的mylist节点,使用访问父节点parentNode,将"HTML/CSS"课程内容输出。

    补充第30行代码,将"HTML/CSS"课程内容输出。

     1 <!DOCTYPE HTML>
     2     <html>
     3     <head>
     4     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     5     <title>无标题文档</title>
     6     </head>
     7     <body>
     8     <ul id="con">
     9     <li id="lesson1">javascript
    10       <ul> 
    11           <li id="tcon"> 基础语法</li>
    12           <li>流程控制语句</li>
    13           <li>函数</li>
    14           <li>事件</li>
    15           <li>DOM</li>
    16       </ul>
    17     </li>
    18     <li id="lesson2">das</li>
    19     <li id="lesson3">dadf</li>
    20     <li id="lesson4">HTML/CSS 
    21       <ul>
    22         <li>文字</li>
    23         <li>段落</li>
    24         <li>表单</li>
    25         <li>表格</li>  
    26       </ul> 
    27     </li></ul>  
    28     <script  type="text/javascript">    
    29        var mylist = document.getElementById("tcon"); 
    30         var f=mylist.parentNode.parentNode.parentNode;
    31         document.write(f.lastChild.innerHTML);
    32     </script> 
    33     
    34     </body>
    35     </html>

    结果:

    2.4、 访问兄弟节点nextSibling和previousSibling

    1.nextSibling属性可返回某个节点之后紧跟的节点(处于同一树层级中)。

    语法:

    nodeObject.nextSibling

    说明:如果无此节点,则该属性返回 null。

    2.previousSibling属性可返回某个节点之前紧跟的节点(处于同一树层级中)。

    语法:

    nodeObject.previousSibling  

    说明:如果无此节点,则该属性返回 null。

    注意: 两个属性获取的是节点。Internet Explorer 会忽略节点间生成的空白文本节点(例如,换行符号),而其它浏览器不会忽略。

    解决问题方法:

    判断节点nodeType是否为1, 如是为元素节点,跳过。

    运行结果:

    LI = javascript
    nextsibling: LI = jquery

     示例代码:

     1 <!DOCTYPE HTML>
     2 <html>
     3 <head>
     4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     5 <title>nextSibling</title>
     6 </head>
     7 <body>
     8 <ul id="u1">   
     9             <li id="a">javascript</li>   
    10             <li id="b">jquery</li>   
    11             <li id="c">html</li>   
    12         </ul>   
    13         <ul id="u2">   
    14             <li id="d">css3</li>   
    15             <li id="e">php</li>   
    16             <li id="f">java</li>   
    17         </ul>   
    18 <script type="text/javascript">
    19     function get_nextSibling(n){
    20         var x=n.nextSibling;
    21         while (x && x.nodeType!=1){
    22             x=x.nextSibling;
    23         }
    24         return x;
    25     }
    26     
    27     function get_previousSibling(n){
    28         var z=n.previousSibling;
    29         while(z && z.nodeType!=1){
    30             z=z.previousSibling;
    31         }
    32         return z;
    33     }
    34 
    35     var x=document.getElementsByTagName("li")[1];
    36     document.write(x.nodeName);
    37     document.write(" = ");
    38     document.write(x.innerHTML);
    39     
    40     var y=get_nextSibling(x);
    41     
    42     if(y!=null){
    43         document.write("<br />nextsibling: ");
    44         document.write(y.nodeName);
    45         document.write(" = ");
    46         document.write(y.innerHTML);
    47     }else{
    48       document.write("<br>已经是最后一个节点");      
    49     }
    50     
    51     var z=get_previousSibling(x);
    52     if(z!=null){
    53         document.write("<br/>previousSibling:");
    54         document.write(z.nodeName);
    55         document.write("=");
    56         document.write(z.innerHTML);
    57     }else{
    58         document.write("<br>已经是第一个节点");
    59     }
    60 
    61 </script>
    62 </body>
    63 </html>

    结果:

    2.5、 插入节点appendChild()

    在指定节点的最后一个子节点列表之后添加一个新的子节点。

    语法:

    appendChild(newnode)

    参数:

    newnode:指定追加的节点。

    我们来看看,div标签内创建一个新的 P 标签,代码如下:

    运行结果:

    HTML
    JavaScript
    This is a new p

     2.6、 插入节点insertBefore()

    insertBefore() 方法可在已有的子节点前插入一个新的子节点。

    语法:

    insertBefore(newnode,node);

    参数:

    newnode: 要插入的新节点。

    node: 指定此节点前插入节点。

    我们在来看看下面代码,在指定节点前插入节点。

    运行结果:

    This is a new p
    JavaScript
    HTML

    注意: otest.insertBefore(newnode,node); 也可以改为:  otest.insertBefore(newnode,otest.childNodes[0]); 

     2.7、 删除节点removeChild()

    removeChild() 方法从子节点列表中删除某个节点。如删除成功,此方法可返回被删除的节点,如失败,则返回 NULL。

    语法:

    nodeObject.removeChild(node)

    参数:

    node :必需,指定需要删除的节点。

    我们来看看下面代码,删除子点。

    运行结果:

    HTML
    删除节点的内容: javascript

    注意: 把删除的子节点赋值给 x,这个子节点不在DOM树中,但是还存在内存中,可通过 x 操作。

    如果要完全删除对象,给 x 赋 null 值,代码如下:

    代码练习:

    试一试,定义clearText()函数,完成节点内容的删除。

    1. 删除该节点的内容,先要获取子节点。

    2. 然后使用循环遍历每个子节点。

    3. 使用removeChild()删除节点。

     1 <!DOCTYPE HTML>
     2 <html>
     3 <head>
     4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     5 <title>无标题文档</title>
     6 </head>
     7 
     8 <body>
     9 <div id="content">
    10   <h1>html</h1>
    11   <h1>php</h1>
    12   <h1>javascript</h1>
    13   <h1>jquery</h1>
    14   <h1>java</h1>
    15 </div>
    16 
    17 <script type="text/javascript">
    18 function clearText() {
    19   var content=document.getElementById("content");
    20   for(var i=content.childNodes.length-1;i>=0;i--){
    21      var childNode = content.childNodes[i];
    22      content.removeChild(childNode);
    23   }
    24 }
    25 </script>
    26 
    27 <button onclick="clearText()">清除节点内容</button>
    28 
    29 
    30 
    31 </body>
    32 </html>

    运行结果:

    2.8、 替换元素节点replaceChild()

    replaceChild 实现子节点(对象)的替换。返回被替换对象的引用。 

    语法:

    node.replaceChild (newnode,oldnew ) 

    参数:

    newnode : 必需,用于替换 oldnew 的对象。 
    oldnew : 必需,被 newnode 替换的对象。

    我们来看看下面的代码:

     

    效果: 将文档中的 Java 改为 JavaScript。

    注意: 

    1. 当 oldnode 被替换时,所有与之相关的属性内容都将被移除。 

    2. newnode 必须先被建立。 

    代码练习:

    试一试,补充函数 replaceMessage() 代码,实现将 b 标签替换成 i 标签。

     1 <!DOCTYPE HTML>
     2 <html>
     3 <head>
     4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     5 <title>无标题文档</title>
     6 </head>
     7 <body>
     8 
     9 
    10   <div><b id="oldnode">JavaScript</b>是一个很常用的技术,为网页添加动态效果。</div>
    11   <a href="javascript:replaceMessage()"> 将加粗改为斜体</a>
    12   
    13     <script type="text/javascript">
    14       function replaceMessage(){
    15           var newnode=document.createElement("i");
    16           var oldnode=document.getElementById("oldnode");
    17           var oldHTML=oldnode.innerHTML;
    18           oldnode.parentNode.replaceChild(newnode,oldnode);
    19           newnode.innerHTML=oldnode.innerHTML;
    20        }    
    21   </script>
    22   
    23  </body>
    24 </html>

    运行结果:

    2.9、 创建元素节点createElement

    createElement()方法可创建元素节点。此方法可返回一个 Element 对象。

    语法:

    document.createElement(tagName)

    参数:

    tagName:字符串值,这个字符串用来指明创建元素的类型。

    注意:要与appendChild() 或 insertBefore()方法联合使用,将元素显示在页面中。

    我们来创建一个按钮,代码如下:

    <script type="text/javascript">
       var body = document.body; 
       var input = document.createElement("input");  
       input.type = "button";  
       input.value = "创建一个按钮";  
       body.appendChild(input);  
     </script>  

    效果:在HTML文档中,创建一个按钮。

    我们也可以使用setAttribute来设置属性,代码如下:

    <script type="text/javascript">  
       var body= document.body;             
       var btn = document.createElement("input");  
       btn.setAttribute("type", "text");  
       btn.setAttribute("name", "q");  
       btn.setAttribute("value", "使用setAttribute");  
       btn.setAttribute("onclick", "javascript:alert('This is a text!');");       
       body.appendChild(btn);  
    </script>  

    效果:在HTML文档中,创建一个文本框,使用setAttribute设置属性值。 当点击这个文本框时,会弹出对话框“This is a text!”。

     代码练习:

    试一试,实现在HTML文档中创建一个链接,并设置相应属性。

    1. 在右边编辑器补充代码,完善createa(url,text)创建链接函数,参数1为链接地址,参数2为链接文本。函数中添加链接地址、文本、文字颜色属性。

    2. 调用createa函数,链接地址 http://www.imooc.com,文本为:慕课网

     1 <!DOCTYPE HTML>
     2 <html>
     3 <head>
     4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     5 <title>无标题文档</title>
     6 </head>
     7 <body>
     8 <script type="text/javascript">
     9 var main = document.body;
    10 //创建链接
    11 function createa(url,text)
    12 {
    13     var a=document.createElement("a");
    14     // a.setAttribute("href",url);
    15     a.href = url;
    16     a.innerHTML=text;
    17     a.style.color="red";
    18     main.appendChild(a);
    19 }
    20 // 调用函数创建链接
    21 createa("http://www.imooc.com","慕课网");
    22 
    23 </script> 
    24 </body>
    25 </html>

    运行结果:

    2.10、 创建文本节点createTextNode()

    createTextNode() 方法创建新的文本节点,返回新创建的 Text 节点。

    语法:

    document.createTextNode(data)

    参数:

    data : 字符串值,可规定此节点的文本。

    我们来创建一个<div>元素并向其中添加一条消息,代码如下:

    运行结果:

    3、 浏览器

    3.1、 浏览器窗口可视区域大小

    获得浏览器窗口的尺寸(浏览器的视口,不包括工具栏和滚动条)的方法:

    一、对于IE9+、Chrome、Firefox、Opera 以及 Safari:

    •  window.innerHeight - 浏览器窗口的内部高度

    •  window.innerWidth - 浏览器窗口的内部宽度

    二、对于 Internet Explorer 8、7、6、5:

    •  document.documentElement.clientHeight表示HTML文档所在窗口的当前高度。

    •  document.documentElement.clientWidth表示HTML文档所在窗口的当前宽度。

    或者

    Document对象的body属性对应HTML文档的<body>标签

    •  document.body.clientHeight

    •  document.body.clientWidth

    在不同浏览器都实用的 JavaScript 方案:

    var w= document.documentElement.clientWidth
          || document.body.clientWidth;
    var h= document.documentElement.clientHeight
          || document.body.clientHeight;

     3.2、 网页尺寸:scrollHeight、scrollWidth

    scrollHeight和scrollWidth,获取网页内容高度和宽度。

    一、针对IE、Opera:

    scrollHeight 是网页内容实际高度,可以小于 clientHeight。

    二、针对NS、FF:

    scrollHeight 是网页内容高度,不过最小值是 clientHeight。也就是说网页内容实际高度小于 clientHeight 时,scrollHeight 返回 clientHeight 。

    三、浏览器兼容性

    var w=document.documentElement.scrollWidth
       || document.body.scrollWidth;
    var h=document.documentElement.scrollHeight
       || document.body.scrollHeight;

    注意:区分大小写

    scrollHeight和scrollWidth还可获取Dom元素中内容实际占用的高度和宽度。

    3.3、 网页尺寸offsetHeight、offsetWidth

    offsetHeight和offsetWidth,获取网页内容高度和宽度(包括滚动条等边线,会随窗口的显示大小改变)。

    一、值

    offsetHeight = clientHeight + 滚动条 + 边框。

    二、浏览器兼容性

    var w= document.documentElement.offsetWidth
        || document.body.offsetWidth;
    var h= document.documentElement.offsetHeight
        || document.body.offsetHeight;

    3.4、 网页卷去的距离与偏移量

    我们先来看看下面的图:

    scrollLeft:设置或获取位于给定对象左边界与窗口中目前可见内容的最左端之间的距离 ,即左边灰色的内容。

    scrollTop:设置或获取位于对象最顶端与窗口中可见内容的最顶端之间的距离 ,即上边灰色的内容。

    offsetLeft:获取指定对象相对于版面或由 offsetParent 属性指定的父坐标的计算左侧位置 。

    offsetTop:获取指定对象相对于版面或由 offsetParent 属性指定的父坐标的计算顶端位置 。

    注意:

    1. 区分大小写

    2. offsetParent:布局中设置postion属性(Relative、Absolute、fixed)的父容器,从最近的父节点开始,一层层向上找,直到HTML的body。

    示例代码:

     1 <!DOCTYPE HTML>
     2 <head>
     3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     4 <script type="text/javascript">
     5     function req(){
     6           var div = document.getElementById("div1");
     7           document.getElementById("li1").innerHTML = (div.offsetTop)+"px";//div1距离屏幕顶部的距离
     8           document.getElementById("li2").innerHTML = (div.offsetLeft)+"px";//div1距离屏幕左部的距离
     9           document.getElementById("li3").innerHTML = (div.scrollTop)+"px";//div1纵向滚动条滚动的距离
    10           document.getElementById("li4").innerHTML = (div.scrollLeft)+"px";//div1横向滚动条滚动的距离
    11      }
    12 </script>
    13 </head>
    14 <body style="border:10px solid #ccc;padding:0px 0px;margin:5px 10px">
    15     <div style="60%;border-right:1px dashed red;float:left;">
    16         <div style="float:left;">
    17             <div id="div1" style="border:5px red solid;height:300px;200px;overflow:auto">
    18                 <div style="height:500px;400px">请调整横竖滚动条后,点击按钮后查看offsetTop、offsetLeft、scrollTop、scrollLeft值。</div>
    19             </div>
    20             <input type="button" value="点击我!" onclick="req()" style="border: 1px solid purple;height: 25px;"/>
    21         </div>
    22         
    23     </div>
    24     <div style="30%;float:left;">
    25         <ul style="list-style-type: none; line-height:30px;">结果:
    26             <li>offsetTop : <span id="li1"></span></li>
    27             <li>offsetLeft : <span id="li2"></span></li>
    28             <li> scrollTop : <span id="li3"></span></li>
    29             <li>scrollLeft : <span id="li4"></span></li>
    30         </ul>
    31         
    32     </div>
    33     <div style="clear:both;"></div>    
    34 </body>
    35 </html>

    演示:调整横竖滚动条后,点击按钮后,查看offsetTop、offsetLeft、scrollTop、scrollLeft值的变化。

     三、编程练习

    制作一个表格,显示班级的学生信息。

    要求:

    1. 鼠标移到不同行上时背景色改为色值为 #f2f2f2,移开鼠标时则恢复为原背景色 #fff

    2. 点击添加按钮,能动态在最后添加一行

    3. 点击删除按钮,则删除当前行

    分析:

    第一步: 首先,我们创建删除函数,并在删除按钮上添加点击事件;

    提示: 使用removeChild()。

    第二步: 编写一个函数,供添加按钮调用,动态在表格的最后一行添加子节点;

    提示: 使用createElement()、innerHTML、appendChild()。

    第三步: 更改鼠标移动改变背景则可以通过给每行绑定鼠标移上事件和鼠标移除事件来改变所在行背景色。

    提示:
    1. 获取表格的行,getElementsByTagName 。
    2. 使用for进行循环,为每行添加事件及背景颜色设置。

    代码:

     1 <!DOCTYPE html>
     2 <html>
     3  <head>
     4   <title> new document </title>  
     5   <meta http-equiv="Content-Type" content="text/html; charset=gbk"/>   
     6   <script type="text/javascript">  
     7      window.onload = function(){
     8         Highlight();
     9      }  
    10      function addOne(obj){ 
    11         var tbody = document.getElementById('table').lastChild;  
    12         var tr = document.createElement('tr');  
    13          
    14          var td = document.createElement("td");
    15          td.innerHTML = "<input type='text'/>";
    16          tr.appendChild(td);
    17          
    18          td = document.createElement("td");     
    19          td.innerHTML = "<input type='text'/>";
    20          tr.appendChild(td);
    21          
    22          td = document.createElement("td");    
    23          td.innerHTML = "<a href='javascript:;' onclick='deleteRow(this)'>删除</a>";
    24          tr.appendChild(td);   
    25          
    26          tbody.appendChild(tr);   
    27         Highlight();
    28         }
    29 
    30      function deleteRow(obj){
    31         var tbody = document.getElementById('table').lastChild;  
    32         var tr = obj.parentNode.parentNode;
    33          tbody.removeChild(tr);
    34      }
    35      function Highlight(){
    36         var tbody = document.getElementById('table').lastChild;    
    37         trs = tbody.getElementsByTagName('tr');   
    38         for(var i =1;i<trs.length;i++){
    39             trs[i].onmouseover = function(){
    40                 this.style.backgroundColor ="#f2f2f2";
    41             } 
    42             trs[i].onmouseout = function(){
    43                 this.style.backgroundColor ="#fff";
    44             } 
    45         }  
    46      }
    47 
    48   </script> 
    49  </head> 
    50  <body> 
    51        <table border="1" width="50%" id="table">
    52        <tr>
    53         <th>学号</th>
    54         <th>姓名</th>
    55         <th>操作</th>
    56        </tr>  
    57 
    58        <tr>
    59         <td>xh001</td>
    60         <td>王小明</td>
    61         <td><a href="javascript:;" onclick="deleteRow(this)">删除</a></td>
    62        </tr>
    63 
    64        <tr>
    65         <td>xh002</td>
    66         <td>刘小芳</td>
    67         <td><a href="javascript:;" onclick="deleteRow(this)">删除</a></td>
    68        </tr>  
    69 
    70        </table>
    71        <input type="button" value="添加一行" onclick="addOne()" />
    72  </body>
    73 </html>

    运行结果:

  • 相关阅读:
    为Android系统内置Java应用程序测试Application Frameworks层的硬件服务
    为Android系统的Application Frameworks层增加硬件访问服务
    为Android硬件抽象层(HAL)模块编写JNI方法提供Java访问硬件服务接口
    为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序
    为Android系统内置C可执行程序测试Linux内核驱动程序
    Android内核驱动程序的编写和编译过程
    添加一个Application Framework Service
    getopt()函数
    Google推Android新开发语言Sky:流畅度 秒iOS
    开发人员要避免的七个心态问题
  • 原文地址:https://www.cnblogs.com/Qian123/p/5217059.html
Copyright © 2020-2023  润新知