从 window 到 DOM

406 阅读6分钟

从 window 到 DOM

注意点:

  • DOM 是浏览器宿主提供的对象, 所以相关代码要在浏览器中打开和调试
  • DOM 是根据 html 长出来的, DOM 相关的 js 代码都是结合 html 的在浏览器环境下运行的 js 代码
  1. 什么是window?

    • window:是一个全局对象, 代表浏览器中一个打开的窗口, 每个窗口都是一个 window 对象
  2. 什么是document?

    • document 是 window 的一个属性, 这个属性是一个对象的引用
    • document: 代表当前窗口中的整个网页
    • document对象保存了网页上所有的内容, 通过 document 对象就可以操作网页上的内容
  3. 什么是DOM?

    • DOM 定义了访问和操作 HTML 文档(网页)的标准方法

    • DOM 全称: Document Object Model, 即文档模型对象

    • 所以学习 DOM 就是学习如何通过 document 对象操作网页上的内容

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Test</title>
      </head>
      <body>
          <script>
              console.log(window.document);
              console.log(typeof window.document);
              console.log(window.document.title);
          </script>
      </body>
      </html>
      

获取 DOM 元素或节点

  • 元素, element, 在 DOM 里指 html 标签的对应对象

  • 节点, node, DOM对象以树的形式保存了界面上所有的内容

    HTML 页面每一部分在 DOM 中都是有对应的节点 (标签(元素),==文本==,属性(已废弃)等等)

  • 所以元素是节点的子集

老牌的 getXX 和现代的 queryXX

  • 在 JavaScript 中 HTML 标签也称之为 DOM 元素
  • 使用 document 的时候前面不用加 window
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test</title>
</head>
<body>
    <script>
        var num = 666;
        console.log(window.num);
        console.log(num);

        // 同理可证
        console.log(window.document);
        console.log(document);
    </script>
</body>
</html>
  1. 通过 id 获取指定元素 .getElementById("idName");
    • 由于 id 不可以重复, 所以找到了就会将找到的标签包装成一个对象返回给我们, 找不到就返回 null
    • 注意点: DOM 操作返回的是一个对象, 这个对象是宿主类型对象(浏览器提供的对象)
  2. 通过class名称获取 .getElementsByClassName("className");
    • 由于 class 可以重复, 所以找到了就返回一个存储了标签对象的数组, 找不到就返回一个空数组
  3. 通过标签属性 name 值获取 .getElementsByName("nameAttributeValue");
    • 由于name可以重复, 所以找到了就返回一个存储了标签对象的数组, 找不到就返回一个空数组
    • 注意点:
      • getElementsByName 在不同的浏览器其中工作方式不同
      • 在IE和Opera中,getElementsByName() 方法还会返回那些 id 为指定值的元素
  4. 通过标签名称获取 .getElementsByTagName("tagName");
    • 由于标签名称可以重复, 所以找到了就返回一个存储了标签对象的数组, 找不到就返回一个空数组
  5. 通过选择器获取 .querySelector(""); (==重点掌握==)
    • querySelector 只会返回根据指定选择器找到的第一个元素
    • 类名用 ., id 名用 #, 各种选择器都用得
  6. 通过选择器获取 .querySelectorAll(""); (==重点掌握==)
    • querySelectorAll 会返回指定选择器找到的所有元素
    • 各种选择器都用得
  7. 关于 get 系和 query 系的区别
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JavaScript-获取DOM元素</title>
</head>
<body>
<div class="father">
    <form>
        <input type="text" name="test">
        <input type="password" name="test">
    </form>
</div>
<div class="father" id="box">我是div</div>

<script>
    let oDiv1 = document.getElementById("box");
    console.log(oDiv1);
    console.log(typeof oDiv1); // object

    let oDivs1 = document.getElementsByClassName("father");
    console.log(oDivs);

    let oDivs2 = document.getElementsByName("test");
    console.log(oDivs);

    let oDivs3 =  document.getElementsByTagName("div");
    console.log(oDivs);

    let oDiv4 = document.querySelector("#box");
    let oDiv5 = document.querySelector(".father");
    let oDiv6 = document.querySelector("div>form");

    let oDivs7 = document.querySelectorAll(".father");
    console.log(oDivs);
</script>
</body>
</html>

通过元素(节点)拿其他元素(节点)

获取父元素, 父节点

  • 由于元素的父节点必然是元素, 所以下面俩方法作用是一样的
let item = document.querySelector(".item");
console.log(item.parentElement);
console.log(item.parentNode);

// 火狐一开始不支持 .parentElement, 现在通用 .parentElement 就好啦
// let parentEle = item.parentElement || item.parentNode;
let parentEle = item.parentElement;
console.log(parentEle);

获取子元素, 子节点

妈的这名字不能很好的见名知意, 差评!

  1. 获取指定元素所有子代

    • .childNodes 拿所有节点
    • .children 拿所有元素
    let oDiv = document.querySelector("div");
    
    // children属性获取到的是指定元素中所有的子元素
    // console.log(oDiv.children);
    
    // childNodes属性获取到的是指定元素中所有的节点
    // console.log(oDiv.childNodes);
    
    for(let node of oDiv.childNodes){
        // console.log(node.nodeType); // 3
        // if(node.nodeType === 1){ // 与第12行等价, 但不够炫酷
        if(node.nodeType === Node.ELEMENT_NODE){
            console.log(node);
        }
    }
    
  2. 获取指定节点中的第一个子代

    • .firstChild 拿第一个子节点
    • .firstElementChild 拿第一个子元素
    let oDiv = document.querySelector("div");
    console.log(oDiv.firstChild);
    console.log(oDiv.firstElementChild);
    
  3. 获取指定节点中的最后一个子代

    • .lastChild 拿最后一个子节点
    • .lastElementChild 拿最后一个子元素
    let oDiv = document.querySelector("div");
    console.log(oDiv.lastChild);
    console.log(oDiv.lastElementChild);
    

获取兄弟元素, 获取兄弟节点

  1. 获取指定节点的相邻上一个兄弟

    • .previousSibling 获取相邻上一个节点
    • .previousElementSibling 获取相邻上一个元素
    let item = document.querySelector(".item");
    
    console.log(item.previousSibling);
    console.log(item.previousElementSibling);
    
  2. 获取指定节点的相邻下一个兄弟

    • .nextSibling 获取相邻下一个节点
    • .nextElementSibling 获取相邻下一个元素
    let item = document.querySelector(".item");
    
    console.log(item.nextSibling);
    console.log(item.nextElementSibling);
    

增删改查

元素节点增删改查

再提醒自己一波: DOM 里元素是节点的子集

    • 创建: document.createElement("elementName");
    • 推入尾部: parentNode.appendChild(newChildNode);
    • 插入节点: parentNode.insertBefore(newChildNode, targetSiblingNode);
    • 只能通过父节点删子节点: childNode.parentNode.removeChild(anotherChildNode);
  1. 改是好大一块, 另外讲
  2. 查就是 queryXX 啦
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JavaScript-元素增删改查</title>
</head>
<body>
<div>
    <h1>我是标题</h1>
    <p>我是段落</p>
</div>
<script>
    // query 出来给增删改查用
    let oDiv = document.querySelector("div");
    let oH1 = document.querySelector("h1");
    let oP = document.querySelector("p");
    
    // 1.创建节点
    let oSpan = document.createElement("span");
    console.log(oSpan); // <span></span>
    console.log(typeof oSpan); // object

    // 2.添加节点	注意点: appendChild方法会将指定的元素添加到最后
    oDiv.appendChild(oSpan)
    let oA = document.createElement("a");
    oDiv.appendChild(oA);

    // 3.插入节点
    oDiv.insertBefore(oSpan, oH1);
    oDiv.insertBefore(oSpan, oP);

    // 5.删除节点	注意点: 在 js 中如果想要删除某一个元素, 只能通过对应的父元素来删除, 元素是不能够自杀的       
    console.log(oSpan.parentNode);
    oSpan.parentNode.removeChild(oSpan);
    // oDiv.parentNode.removeChild(oDiv); wrong play

    // 5.克隆节点	注意点: cloneNode方法默认不会克隆子元素, 如果想克隆子元素需要传递一个true
    // let newDiv =  oDiv.cloneNode();
    let newDiv =  oDiv.cloneNode(true);
    console.log(newDiv);
</script>
</body>
</html>

属性节点增删改查 (废弃节点)

关键点: 元素节点的默认属性可以通过 . 操作来实现 但自定义属性的增改删查要用到 .setAttribute, .removeAttribute, .getAttribute

 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JavaScript-元素属性操作</title>
</head>
<body>
<img src="images/1.jpg" alt="我是alt222" title="我是title" fhs="666">
<script>
    /*
    无论是通过document创建还是查询出来的标签,系统都会将元素包装成一个对象返回给我们,
    系统在包装这个对象的时候会自动将元素的属性都包装到这个对象中,
    所以只要拿到这个对象就可以拿到标签属性,操作标签属性
    */
    
    // let oImg = document.querySelector("img");
    let oImg = document.createElement("img");
    console.dir(oImg);

    // 1.如何获取元素属性
    let oImg = document.querySelector("img");
    // console.log(oImg.alt);
    // console.log(oImg.getAttribute("alt"));
    /*
    注意点: 
    通过对象.属性名称的方式无法获取到自定义属性的取值
    通过getAttribute方法可以获取到自定义属性的取值
	*/
    console.log(oImg.nj); // undefined
    console.log(oImg.getAttribute("fhs"));

    // 2.如何修改元素属性
    let oImg = document.querySelector("img");
    // oImg.title = "新的title";
    // oImg.setAttribute("title", "新的title222");
    // 注意点和获取元素属性一样
    // oImg.fhs = "123";
    oImg.setAttribute("fhs", "123");

    // 3.如何新增元素属性
    /*
    let oImg = document.querySelector("img");
    // oImg.it666 = "it";
    // 注意点: setAttribute方法如果属性不存在就是新增, 如果属性存在就是修改
    oImg.setAttribute("it666", "itzb");
    */

    // 4.如何删除元素属性 通过父元素节点删除子属性节点
    let oImg = document.querySelector("img");
    // oImg.alt = "";
    // oImg.removeAttribute("alt");
    // 注意点和获取元素属性一样
    // oImg.nj = ""; // 不管用
    oImg.removeAttribute("fhs");
</script>
</body>
</html>

玩转元素

操作元素内容

  1. 获取元素内容
    • .innerHTML
    • .innerText
    • .textContent
    • innerText 和 textContext 作用是一样的, 只不过不同浏览器支持的方法名有不同
  2. 给上面的属性赋值就好了
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JavaScript-元素内容操作</title>
</head>
<body>
<div>
    我是div
    <h1>我是标题</h1>
    <p>我是段落</p>
</div>
<script>
   // 1.获取元素内容
   /*
   1.innerHTML获取的内容包含标签, innerText/textContent获取的内容不包含标签
   2.innerHTML/textContent获取的内容不会去除两端的空格, innerText获取的内容会去除两端的空格
   */
   let oDiv = document.querySelector("div");
   console.log(oDiv.innerHTML);
   console.log(oDiv.innerText);
   console.log(oDiv.textContent);

   // 2.设置元素内容
   /*
   共性:
   无论通过 innerHTML/innerText/textContent 设置内容, 新的内容都会覆盖原有的内容
   区别:
   如果通过 innerHTML 设置数据, 数据中包含标签, 会转换成标签之后再添加
   如果通过 innerText/textContent 设置数据, 数据中包含标签, 不会转换成标签, 会当做一个字符串直接设置
   */
    let oDiv = document.querySelector("div");
   // oDiv.innerHTML = "123";
   // oDiv.innerText = "456";
   // oDiv.textContent = "789";
   //  oDiv.innerHTML = "<span>我是span</span>";
   //  oDiv.innerText = "<span>我是span</span>";
   //  oDiv.textContent = "<span>我是span</span>";

    setText(oDiv, "www.it666.com");
    function setText(obj, text) {
        if("textContent" in obj){
            obj.textContent = text;
        }else{
            obj.innerText = text;
        }
    }
</script>
</body>
</html>

操作元素样式

通过 JavaScript 设置 CSS 样式注意点:

  • JS 可以通过给元素添加类名修改 style 对象相应属性值的方式来设置 CSS 样式 JS 通过 style 属性只能拿到行内样式的值, ==拿不到== CSS 文件中设置的样式 JS 通过 window.getComputedStyle(selector); 可以==拿到==对应选择器的 css 对象, 从而修改外链样式
  • CSS 中通过短杠连接的属性名在 JS 中以驼峰形式出现
  • 通过 js 添加的 css 属性是行内样式, 优先级高于 css 文件设置的样式
    • .className
    • .style
    • .getComputedStyle(Element)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JavaScript-操作元素样式</title>
    <style>
        .box{
            width: 200px;
            height: 200px;
            background-color: red;
        }
    </style>
</head>
<body>
<div class="box"></div>
<script>
    // 1.设置元素样式
    /*
    let oDiv = document.querySelector("div");
    // 第一种方式
    // 注意点: 由于class在JS中是一个关键字, 所以叫做className
    // oDiv.className = "box";
    // 第二种方式
    // 注意点: 过去CSS中通过-连接的样式, 在JS中都是驼峰命名
    // 注意点: 通过JS添加的样式都是行内样式, 会覆盖掉同名的CSS样式
    oDiv.style.width = "300px";
    oDiv.style.height = "300px";
    oDiv.style.backgroundColor = "blue";
    */

    // 2.获取元素样式
    let oDiv = document.querySelector("div");
    // oDiv.style.width = "300px";
    // 注意点: 通过style属性只能过去到行内样式的属性值, 获取不到CSS设置的属性值
    // console.log(oDiv.style.width);
    // 注意点: 如果想获取到CSS设置的属性值, 必须通过getComputedStyle方法来获取
    // getComputedStyle方法接收一个参数, 这个参数就是要获取的元素对象
    // getComputedStyle方法返回一个对象, 这个对象中就保存了CSS设置的样式和属性值
    let style = window.getComputedStyle(oDiv);
    console.log(style.width);
</script>
</body>
</html>

点击事件

  1. 什么是事件?
    • 用户和浏览器之间的交互行为我们就称之为事件, 比如:点击,移入/移出
  2. 如何给元素绑定事件?
    • 在 JavaScript 中所有的HTML标签都可以添加事件
    • 元素.事件名称 = function(){};
    • 当对应事件被触发时候就会自动执行function中的代码
  3. 注意点:
    • 如果给元素添加了和系统同名的事件 (比如 a 标签的跳转), 我们添加的事件不会覆盖系统添加的事件
    • 通过 元素.事件名称 = function(){}; 的函数体里 return false; 可以禁用系统默认事件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>08-JavaScript-DOM事件</title>
</head>
<body>
    <button>我是按钮</button>
    <a href="http://www.it666.com">我是a标签</a>
<script>
    let oBtn = document.querySelector("button");
    oBtn.onclick = function () {
        alert("按钮被点击了");
    }
    // 注意点: 如果给元素添加了和系统同名的事件, 我们添加的事件不会覆盖系统添加的事件
    let oA = document.querySelector("a");
    oA.onclick = function () {
        alert("a标签被点击了");
        // 以下代码的含义: 用我们添加的事件覆盖掉系统同名的事件
        return false;
    }
</script>
</body>
</html>