JS中的浏览器对象模型-DOM(一)

发布时间 2023-07-25 16:08:18作者: 崎岖行者

document对象中,document元素的选取、修改、添加、删除是常见的应用。

元素的选取

下面一段HTML代码,我们可以非常方便地选取指定的元素。例如:

  <!-- HTML结构 -->
  <div id="test-div">
      <div class="c-red">
          <p id="test-p">JavaScript</p>
          <p>Java</p>
      </div>
      <div class="c-red c-green">
          <p>Python</p>
          <p>Ruby</p>
          <p>Swift</p>
      </div>
      <div class="c-green">
          <p>Scheme</p>
          <p>Haskell</p>
      </div>
  </div>

现在的问题是,要如何选取JavaScript元素?元素的选取可以有三种方式:

  • getElementById(),通过元素id获取元素;
  • getElementsByClassName(),通过class名称获取元素集合
  • getElementsByTagName(),通过标签名称获取元素集合
  //如何选择<p>JavaScript</p>:
  var p1 = document.getElementById("test-p");  //方法一
  var p2 = document.getElementsByClassName("c-red")[0].firstElementChild; //方法二 
  var p3 = document.getElementById("test-div").firstElementChild.firstElementChild; //方法三
  console.log(p1.innerText === p2.innerText,p1.innerText===p3.innerText);
        
  // 选择<p>Python</p>,<p>Ruby</p>,<p>Swift</p>:
  var p4 = document.getElementsByClassName("c-red c-green")[0].children;
        
  // 选择<p>Haskell</p>:
  var p6 = document.getElementsByClassName("c-green")[1].lastElementChild;
  var p7 = document.getElementsByClassName("c-green")[1].children[1];
  var p8 = document.getElementsByTagName("p")[6];
  console.log(p6.innerText === p8.innerText,p7.innerText === p8.innerText);

firstElementChild表示元素的第一个子元素。lastElementChild表示元素的最后一个子元素。

getElementsByClassName()和getElementsByTagName()方法获取的是一元素集合,定位到具体的元素需要加索引。

元素的选取还可以使用querySelector()和querySelectorAll()获取

  • querySelector(),获取给定选择器后查询到的第一个节点。
  • querySelectorAll(),获取给定选择器后查询到的节点集合。
  // 选择<p>Python</p>,<p>Ruby</p>,<p>Swift</p>:
  var p5 = document.querySelectorAll(".c-red.c-green>p");

.c-red表示c-red class选择器,.c-green表示c-green class选择器,两个class选择器之间没有空格表示且的关系,“>”表示子选择器。如果两个class选择器类型之间用逗号隔开表示或的关系。

节点和元素的区别

在HTML中标签以及标签所包裹的内容是一个元素;节点包括元素、comment、文本等。例如

  <div id="div1">
      这是一个大框
      <!-- 下面是一个内部框  -->
      <div id="div2">
          内部框
      </div>
  <div>

上述代码中,div1元素下包括三个节点,一个文本节点、一个注释节点、一个div2元素节点。然而,div1元素下只有一个div2元素。

修改DOM

通过innerText属性,获取或修改元素的文本,通过innerHtml属性,获取或修改元素的HTML内容。

下面一段HTML代码,我们可以非常方便地修改元素。例如:

  <h1>JS DOM UPDATE</h1>
  <!-- HTML结构 -->
  <div id="test-div">
      <p id="test-js">javascript</p>
      <p>Java</p>
  </div>

要如何修改javascript为JavaScript?

  // 获取<p>javascript</p>节点:
  var js = document.getElementById("test-js");
  // 修改文本为JavaScript:
  // TODO:
  js.innerText="JAVASCRIPT";

修改元素的样式属性

  var js = document.getElementById("test-js");
  // 修改CSS为: color: #ff0000, font-weight: bold
  js.style.color="#ff0000";
  js.style.fontWeight = "bold";
  //
  js.setAttribute("style","color:#ff0000;font-size:30px");

通过元素的style属性修改,通过setAttribute方法进行修改两种方法是等效的。

插入DOM

插入DOM有两种方式:

  • 第一种方式,先找到父元素,然后使用appendChild()方法,把元素添加到子元素的最后;
  • 第二种方式,先找到父元素,然后使用insertBefore()方法,在它的某一子元素前面添加元素

下面一段HTML代码为例:

  <!-- HTML结构 -->
  <ol id="test-list">
      <li class="lang">Scheme</li>
      <li class="lang">JavaScript</li>
      <li class="lang">Python</li>
      <li class="lang">Ruby</li>
      <li class="lang">Haskell</li>
  </ol>

使用insertBefore,在Ruby元素前面添加Css元素

  var css = document.createElement("li");
  css.className="lang";
  css.innerText="Css";
  var testList = document.getElementById("test-list");
  var ruby = testList.children[3];
  testList.insertBefore(css,ruby);

使用appendChild,在ol列表末尾添加一项Css语言

  var css = document.createElement("li");
  css.className="lang";
  css.innerText="Css";
  var testList = document.getElementById("test-list");
  testList.appendChild(css);

删除DOM

要删除一个节点,首先要获得该节点本身以及它的父节点,然后,调用父节点的removeChild把自己删掉:

  // 拿到待删除节点:
  var self = document.getElementById('to-be-removed');
  // 拿到父节点:
  var parent = self.parentElement;
  // 删除:
  var removed = parent.removeChild(self);
  removed === self; // true

以下面HTML结构为例:

  <!-- HTML结构 -->
  <ul id="test-list">
      <li>JavaScript</li>
      <li>Swift</li>
      <li>HTML</li>
      <li>ANSI C</li>
      <li>CSS</li>
      <li>DirectX</li>
  </ul>

请删除与网页开发无关的语言

  //拿到父节点
  var list = document.getElementById("test-list");
  var arrRemoved = ["Swift","ANSI C","DirectX"];
  //分别删除数组种的语言
  arrRemoved.forEach(x =>{
      var lis = document.getElementsByTagName("li")
      var element = Array.from(lis).find(e=>e.innerText == x);
          list.removeChild(element);
      })

表单

用JavaScript操作表单和操作DOM是类似的,因为表单本身也是DOM树。

表单可以接收用户的输入内容,HTML表单的输入控件主要有以下几种:

  • 文本框,对应的<input type="text">,用于输入文本;
  • 口令框,对应的<input type="password">,用于输入口令;
  • 单选框,对应的<input type="radio">,用于选择一项;
  • 复选框,对应的<input type="checkbox">,用于选择多项;
  • 下拉框,对应的<select>,用于选择一项;
  • 隐藏文本,对应的<input type="hidden">,用户不可见,但表单提交时会把隐藏文本发送到服务器;
  • 日期框,对应的<input type="date">,输入日期;
  • 日期时间框,对应的<input type="datetiem-local">,输入日期时间;
  • 颜色框,对应的<input type="color">,输入颜色;
  • 按钮<input type="button">,用于按钮。

获取值

如果我们获得了一个<input>节点的引用,就可以直接调用value获得对应的用户输入值:

  // <input type="text" id="email">
  var input = document.getElementById('email');
  input.value; // '用户输入的值'

对于单选框和复选框,value属性返回的永远是HTML预设的值,而我们需要获得的实际是用户是否“勾上了”选项,所以应该用checked判断:

  //<label><input type="radio" name="weekday" id="monday" value="1"> Monday</label>
  //<label><input type="radio" name="weekday" id="tuesday" value="2"> Tuesday</label>
  var mon = document.getElementById('monday');
  var tue = document.getElementById('tuesday');
  mon.value; // '1'
  tue.value; // '2'
  mon.checked; // true或者false
  tue.checked; // true或者false

设置值

设置值和获取值类似,对于text、password、hidden以及select,直接设置value就可以:

  // <input type="text" id="email">
  var input = document.getElementById('email');
  input.value = 'test@example.com'; // 文本框的内容已更新

提交表单

下面一段HTML代码,按要提交输入信息:

  <!-- HTML结构 -->
  <form id="test-register" action="#" target="_blank" onsubmit="return checkRegisterForm()">
      <p id="test-error" style="color:red"></p>
      <p>
          用户名: <input type="text" id="username" name="username">
      </p>
      <p>
          口令: <input type="password" id="password" name="password">
      </p>
      <p>
          重复口令: <input type="password" id="password-2">
      </p>
      <label><input type="radio" name="weekday" id="monday" value="1" checked/> Monday</label>
      <label><input type="radio" name="weekday" id="tuesday" value="2" /> Tuesday</label>
      <p>
          <input type="submit" value="提交"/> <input type="reset" value="重置"/>
      </p>
  </form>
对应的js代码如下:
  // 用户名必须是3-10位英文字母或数字;
  // 口令必须是6-20位;
  // 两次输入口令必须一致。
  function checkRegisterForm(){
      var username = document.getElementById("username").value;
      var password = document.getElementById("password").value;
      var password2 = document.getElementById("password-2").value;
      console.log(username,password,password2);
      if (username.length>=3 && username.length<=10){
          if (password.length>=6 && password.length<=20){
              if (password2.length>=6 && password2.length<=20){
                  if (password == password2){
                      return true;
                  }
              }
          }
      }
      return false;
  }

上述代码种,当点击提交按钮时,执行form的onsubmit事件,完成表单的提交。

AJAX

AJAX不是JavaScript的规范,它是Asynchronous JavaScript and XML的缩写,意思就是用JavaScript执行异步网络请求。

用Form提交数据,点击“提交”按钮,表单开始提交,浏览器就会刷新页面。

如果要让用户留在当前页面中,同时发出新的HTTP请求,就必须用JavaScript发送这个新请求,接收到数据后,再用JavaScript更新页面, 这样一来,用户就感觉自己仍然停留在当前页面,但是数据却可以不断地更新。

在现代浏览器上写AJAX主要依靠XMLHttpRequest对象:

  var request;
  if (window.XMLHttpRequest) {
      request = new XMLHttpRequest();
  } else {
      request = new ActiveXObject('Microsoft.XMLHTTP');
  }
        
  function success(text) {
      var textarea = document.getElementById('test-ie-response-text');
      textarea.value = text;
  }
        
  function fail(code) {
      var textarea = document.getElementById('test-ie-response-text');
      textarea.value = 'Error code: ' + code;
  }
        
  request.onreadystatechange = function () { // 状态发生变化时,函数被回调
      if (request.readyState === 4) { // 成功完成
          // 判断响应结果:
          if (request.status === 200) {
              // 成功,通过responseText拿到响应的文本:
              return success(request.responseText);
          } else {
              // 失败,根据响应码判断失败原因:
              return fail(request.status);
          }
      } else {
          // HTTP请求还在继续...
      }
  }
        
  // 发送请求:
  request.open('GET', '/api/categories');
  request.send();
  alert('请求已发送,请等待响应...');

文章同时发表在:码农编程网 欢迎访问

本节重点:

  • 如何选取document元素;
  • document元素的查询、修改、添加、删除等操作。
  • 表单元素的介绍;
  • 表单元素值的获取和设置;
  • 表单提交。
  • 什么是AJAX,在JavaScript中如何使用异步请?