Javascript学习笔记 for 《javascript_DOM编程艺术》

😼 Basic Syntax

  • 程序语言分解释型语言与编译型语言两种,前者只需有解释器(对Javascript代码来说是浏览器),后者要有编译器。
  • js是一种基于对象的语言,而不是面向对象的语言。
  • 语句:js脚本由一系列指令构成,这些指令叫语句,每条语句后加分号。
  • 注释: 多行 / / 单行 <!-- //。
  • 命名:变量用下划线;函数用驼峰命名法。
  • 变量:声明(var 变量名)与赋值。
  • 数据类型:js为弱类型语言;字符串由引号包围(双单均可);用反斜线对字符进行转义,如要在字符串中包含"(此字符串由双引号包围),则需用\";数值;布尔值;
  • 数组:语法举例 var a = Array(4)(声明,数组元素个数4完全可以不写);a[0]=1(填充);a[1]=2; or var a = Array(1,2,3,4); or var a = [1,2,3,4]; or var a = [];a[0]=1; 数组中元素数据类型不需相同;关联数组 可在填充数组时为每个新元素明确地给出下标,这时下标不一定要用数字还可用字符串。
  • 对象:var a = Object()(也可直接var a={};); a.year=0; a.month=1; or var a = {year:0, month:1}; 可把对象作为数组元素。
  • 操作:算数操作符
  • 条件语句:
  • 比较操作符:==认为空字符串与false的含义相同,要进行严格比较须用全等操作符===,!=也是如此。
  • 逻辑运算符:或 与 非
  • 循环语句:while do while for
  • 函数:function don(){ } 用var关键字给函数变量规定作用域,如没有用var则被视为全局变量
  • 对象:一种自足的数据集合。假设Person是个内建对象,则可用var Jiadon = new Person;来新建对象的实例,然后就可用Jiadon.age、Jiadon.walk()等来使用对象的属性和方法。
  • 内建对象举例:Math对象的round方法可把十进制数值舍为最接近的整数,如var res=Math.round(num);Date对象——var current_date=new Date(); var today = current_date.getDay(); 还有getHours,getDate,getMonth
  • 宿主对象:由js运行环境提供如浏览器,由浏览器提供的预定义对象称为host object。如Form、Image、document对象。
  • 用户定义对象

🎂 DOM

  • DOM与js的关系:

DOM 是 JavaScript 操作网页的接口,全称为“文档对象模型”(Document Object Model)。它的作用是将网页转为一个 JavaScript 对象,从而可以用脚本进行各种操作(比如增删内容)。

浏览器会根据 DOM 模型,将结构化文档(比如 HTML 和 XML)解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree)。所有的节点和最终的树状结构,都有规范的对外接口。

DOM 只是一个接口规范,可以用各种语言实现。所以严格地说,DOM 不是 JavaScript 语法的一部分,但是 DOM 操作是 JavaScript 最常见的任务,离开了 DOM,JavaScript 就无法控制网页。另一方面,JavaScript 也是最常用于 DOM 操作的语言。后面介绍的就是 JavaScript 对 DOM 标准的实现和用法。

  • 节点的类型有七种。

    Document:整个文档树的顶层节点 DocumentType:doctype标签(比如<!DOCTYPE html>) Element:网页的各种HTML标签(比如<body>、<a>等) Attribute:网页元素的属性(比如class="right") Text:标签之间或标签包含的文本 Comment:注释 DocumentFragment:文档的片段

获取元素:

  • 有三种DOM方法可获取元素节点:getElementById() getElementsByTagName() getElementsByClassName(). 参数必须要用双引号包围。返回对象或对象数组。可用typeof document.getElementById()来获取返回数据的类型。
  • 简要总结:一份文档就是一棵节点树。节点分为不同类型:元素节点 属性节点 文本节点。getElementById()返回一个对象,该对象对应文档里一个特定的元素节点。getElementsByTagName() getElementsByClassName() 返回一个对象数组,它们分别对应着文档里一组特定的元素节点。每个节点都是一个对象。

获取和设置属性:

  • getAttribute():此方法不属于document对象,须用元素节点(对象)来调用。

Example:

var a = document.getElementsByTagName("a");
for(var i = 0; i<a.length; i++){
    var att = a[i].getAttribute("href");
    if(att) alert(att);     
}
  • setAttribute():与getAttribute类似。

Example:

var a = document.getElementsByTagName("a");
for(var i = 0; i<a.length; i++){
    var att = a[i].getAttribute("href");
    if(att){
        alert(a[i].getAttribute("href")); 
        a[i].setAttribute("href", "google.com");
        alert(a[i].getAttribute("href"));    
    }    
}

🎃 案例研究:js图片库

    <!--gallery.html: -->
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
    <head>
        <meta name="keywords" content="Pictures Animals" />
        <link type="text/css" rel="stylesheet" href="gallery.css"/>
        <title>Gallery</title>
    </head>

    <body>
        <h1>Animal Pictures</h1>
        <ul>
            <li><a href="images/horse.jpg" title="a handsome horse" onclick="showPic(this); return false;">horse</a></li>
            <li><a href="images/grass.jpg" title="lovely grass" onclick="showPic(this); return false;">grass</a></li>
            <li><a href="images/bird.jpg" title="a rutting bird" onclick="showPic(this); return false;">bird</a></li>
            <li><a href="images/squirrel.jpg" title="squirrel" onclick="showPic(this); return false;">squirrel</a></li>
        </ul>
        <img src="images/placeholder.jpg" alt="my image gallery" id="placeholder"/>
        <script type="text/javascript" src="scripts/gallery.js"></script>
        <p id="textholder">Please choose an image.</p>
    </body>
    </html>
    //gallery.js: 
    function showPic(whichPic){
        var source = whichPic.getAttribute("href");
        var placeholder = document.getElementById("placeholder");
        placeholder.setAttribute("src", source);//也可用:placeholder.src=source;

        var text = whichPic.getAttribute("title");
        var textholder = document.getElementById("textholder");
        textholder.firstChild.nodeValue = text;//也可用childNodes[0]代替firstChild
    }

    function countBodyChildren(){
        var body_element = document.getElementsByTagName("body")[0];
        alert(body_element.childNodes.length); //childNodes属性返回的数组包含所有类型的节点
        //alert(body_element.nodeType); 元素节点显示为1,属性为2,文本为3
    }

    window.onload = countBodyChildren;
    /*gallery.css: */
    body {
        font-family: 'Courier New', Courier, monospace;
        color: #333333;
        background-color: #ccc;
        border: thick brown groove;
        margin: 50px;
        padding: 50px;
    }   

    h1 {
        color: #333333;
        background-color:transparent;
        border-bottom: black medium solid;
    }

    a{
        color: #c60;
        background-color:transparent;
        font-weight:bold;
        text-decoration:none;
        font-size:1.5em;
    }

    a:visited{color:red;}
    a:hover{color:yellow;}
    a:active{color:white;}

    ul{
        padding:0;
    }

    li{
        float:left;
        padding:1em;
        padding-bottom:1.5em;
        list-style: none;
    }

    img{
        display:block;    clear:both;
    }
  • 出现的新属性:chileNodes firstChild lastChild nodeType nodeValue

🍄 最佳实践

  • 在HTML代码中调用函数:

  • "javascript:"伪协议,如 <a href="javascript:popUp(this.href);">pop up<a>

  • 内嵌的事件处理程序,如上一个案例。

  • 分离HTML与js。

  • 平稳退化的概念

  • 分离js
  • 向后兼容
  • 对象检测,如:有一个使用了getElementById()方法的函数,就可以使用对象检测来检查浏览器是否支持这个方法,只需将document.getElementById作为if条件判断表达式,而if中放置你想使用的那个方法。
  • 浏览器嗅探技术
  • 脚本性能考虑:尽量少访问DOM和尽量减少标记。合并放置脚本,将脚本统一放在一个脚本文件中。用软件压缩脚本以减小文件大小。

🏈 案例研究:图片库改进版

//gallery.js: 
function prepareGallery(){
    if(!document.getElementById) return false;
    if(!document.getElementsByTagName) return false;
    if(!document.getElementById("imagegallery")) return false;

    var gallery = document.getElementById("imagegallery");
    var links = gallery.getElementsByTagName("a");

    for(var i = 0; i<links.length; i++){
        links[i].onclick = function(){return !showPic(this);};
    }
}

function showPic(whichPic){

    if(!document.getElementById("placeholder")) return false;
    var source = whichPic.getAttribute("href");
    var placeholder = document.getElementById("placeholder");
    placeholder.setAttribute("src", source);//也可用:placeholder.src=source;

    if(document.getElementById("textholder")){
        var text = whichPic.getAttribute("title")?whichPic.getAttribute("title"):"none";
        var textholder = document.getElementById("textholder");
        textholder.firstChild.nodeValue = text;//也可用childNodes[0]代替firstChild
    }

    return true;
}

//addLoadEvent(prepareGallery);
window.onload = prepareGallery;
  • 键盘访问(目前不已经需要)
  • DOM Core 和 HTLML-DOM

👽 动态创建标记

  • document.write(): 可以方便地写入HTML内容,缺点是它违背了“行为应该与表现分离”的原则。
  • innerHTML属性: 全部替换HTML内容,不支持XHTML
  • DOM方法(不行):
  • 先创建新元素,再把这个新元素插入节点树。如:var para = document.createElement("p"); var testdiv = document.getElementById("testdiv"); testdiv.appendChild(para);
  • 创建文本节点。如:var txt = document.creatTextNode("Hello world!"); para.appendChild(txt);
  • 一个更复杂的组合:可先把所有节点创建出来然后再把它们连在一起;也可如上面一样做。
  • 改进图片库
  • 在已有元素前插入新元素:insertBefore方法,语法parentNode.insertBefore(newElement, tagetElement);
  • 在已有元素后插入新元素:自建insertAfter方法,具体见下面代码。
  • 最终版的gallery: ```javascript function prepareHolder(){ //动态创建标记 var placeholder = document.createElement("img"); var textholder = document.createElement("p"); var txt = document.createTextNode("Please choose an image. ");

    placeholder.setAttribute("id", "placeholder"); placeholder.setAttribute("alt", "my image gallery"); placeholder.setAttribute("src", "images/placeholder.jpg"); textholder.setAttribute("id", "textholder"); textholder.appendChild(txt);

    //document.getElementsByTagName("body")[0].appendChild("placeholder"); //document.getElementsByTagName("body")[0].appendChild("textholder");

    var gallery = document.getElementById("imagegallery"); insertAfter(placeholder, gallery); insertAfter(textholder, placeholder); }

function prepareGallery(){ //平稳退化、对象检测、分离HTML与js if(!document.getElementById) return false; if(!document.getElementsByTagName) return false; if(!document.getElementById("imagegallery")) return false;

var gallery = document.getElementById("imagegallery");
var links = gallery.getElementsByTagName("a");

for(var i = 0; i<links.length; i++){
    links[i].onclick = function(){return !showPic(this);};
}

}

function showPic(whichPic){ //执行刷新的主要功能

if(!document.getElementById("placeholder")) return false;
var source = whichPic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
placeholder.setAttribute("src", source);//也可用:placeholder.src=source;

if(document.getElementById("textholder")){
    var text = whichPic.getAttribute("title")?whichPic.getAttribute("title"):"none";
    var textholder = document.getElementById("textholder");
    textholder.firstChild.nodeValue = text;//也可用childNodes[0]代替firstChild
}

return true;

}

function insertAfter(newElement, targetElement){ var parent = targetElement.parentNode; if(parent.lastChild == targetElement){ parent.appendChild(newElement); }else{ parent.insertBefore(newElement, targetElement.nextSibling);//对应的还有previousSibling } }

//addLoadEvent(prepareGallery); window.onload = function(){ //调用函数 prepareHolder(); prepareGallery(); }


- Ajax
- 异步请求

充实文档的内容
------------------------------------
- 定义缩略语列表:
```javascript
function displayList(){
    //获取所有符合元素节点
    var abbreviation = document.getElementsByTagName("abbr");
    if(abbreviation.length<1) return false;

    //将值保存在数组中
    var defs = Array();
    for(var i = 0; i<abbreviation.length; i++){
        var defination = abbreviation[i].getAttribute("title");
        var key = abbreviation[i].lastChild.nodeValue;
        defs[key] = defination; 
    }

    //创建dl标记
    var dlist = document.createElement("dl");


    //创建多个dt dd标记
    for(key in defs){
        var defination = defs[key];
        var dtitle = document.createElement("dt");
        var ddesc = document.createElement("dd");

        var dt_text = document.createTextNode(key);
        var dd_text = document.createTextNode(defination);

        dtitle.appendChild(dt_text);
        ddesc.appendChild(dd_text);

        dlist.appendChild(dtitle);
        dlist.appendChild(ddesc);
    }

    //创建标题
    var header = document.createElement("h1");
    var header_txt = document.createTextNode("LIST: ");
    header.appendChild(header_txt);

    //添加标题和定义列表到页面主体
    document.body.appendChild(header);
    document.body.appendChild(dlist);
}

//调用
window.onload = displayList;
  • 显示文件来源链接表:

    function displayCitation(){
      var quotes = document.getElementsByTagName("blockquote");
    
      if(quotes.length<1) return false;
      for(var i = 0; i<quotes.length; i++){
          if(!quotes[i].getAttribute("cite")) return false;
          var url = quotes[i].getAttribute("cite");
    
          var quote_elements = quotes[i].getElementsByTagName('*');
          if(quote_elements.length<1) continue;
          var elem = quote_elements[quote_elements.length-1];
    
          var  lin = document.createElement("a");
          var lin_txt = document.createTextNode("source");
          lin.appendChild(lin_txt);
          lin.setAttribute("href", url);
          var superscript = document.createElement("sup");
          superscript.appendChild(lin);
          elem.appendChild(superscript);
      }
    }
    window.onload = displayCitation;
    

🐹 CSS-DOM

  • CSS与DOM也有重叠的部分。
  • 获取样式:不仅文档里每个元素都是一个对象,每个元素都是有一个style属性,它们返回的是对象而不是简单的字符串。但只有把CSS style属性插入到标记里,才可以用DOM style属性去查询那些信息。在外部样式表里声明的样式不会进入style属性返回的对象的属性中。用element.style.property来访问。(font-family属性应写成fontFamily,因为- +在js里是保留字符)。
  • 设置样式:element.style.property = value (style对象的属性值永远是一个字符串)。

201907

results matching ""

    No results matching ""