前端开发(HTML,CSS,VUE,JS)从入门到精通!第四天(DOM编程和AJAX异步交互)

发布于:2025-08-04 ⋅ 阅读:(11) ⋅ 点赞:(0)

八、DOM 编程

1.DOM(Document Object Model),文档对象模型:

将 HTM L文档进行模型化处理,形成一颗结构化的文档树,从而提供访问,修改文档的统一编程接口(API),一旦掌握 DOM 编程,就可以使用 JavaScript 操作整个 HTM L文档。(将 HTML 元素(HTML标签)抽象成一个一个的 DOM 对象,然后通过 JavaScript 来访问)

2.HTML 文档可以抽象成一颗 DOM 树,如下图:

HTML 文档通过浏览器解释执行之后形成了一颗 DOM 树,树上的每一个元素都是 DOM 对象,称为一个节点,然后节点又分为普通元素节点,属性节点,文本节点等等。

3.补充知识:BOM 对象(Browser Object Model),浏览器对象模型

(1)window 对象:

代表整个浏览器对象,是一个全局的对象,我们在 JavaScript 中声明的全局变量和全局函数默认情况下都归属于window 对象,window 对象是全局唯一的,在访问其属性和方法的时候,可以省略掉 “window.” 前缀

(2)window 对象常用的属性:

document:文档对象,比如 document.write(内容) 等效于 window.document.write(内容)。

location:代表浏览器地址栏中的 url 地址

history:浏览器的历史记录

示例:

(3)window 对象的常用方法

alert():弹出提示框

prompt(提示信息):弹出输入框

var res = setInterval(函数, 定时时间):定时器,周期性的执行函数的代码,定时时间为毫秒记

clearInterval(res):关闭定时器

var res = setTimeout(函数,到期时间):设置一个到期时间之后执行一次函数就退出

clearTimeout(res):关闭Timeout

示例:轮播图

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo33</title>
  <style>
    *{
      margin: 0;
      padding: 0;
    }
    div.box{
      width: 600px;
      height: 450px;
      margin: 40px auto;
      border: 2px solid #ccc;
    }
    div.box > img{
      width: 600px;
      height: 450px;
    }
  </style>
</head>
<body>
  <div class="box">
    <img src="images/1.jpg" alt="" id="img">
  </div>
  <script>
    var i = 0;//全局变量
    //获取 img 这个 dom 对象
    var img = document.getElementById("img");
    //定时器:第一个参数为周期执行的函数,第二个参数为定时时间,毫秒记
    setInterval(function () {
      //重新给 img 这个 dom 对象的 src 属性赋值,切换图片
      img.src = "images/" + ++i + ".jpg";
      if(i >= 4){ //总共4副图片
        i = 0;
      }
    }, 1000);
  </script>
</body>
</html>

4.访问 HTML 元素(DOM对象)

(1)访问 HTML 元素有两种方式

① 使用 document 对象提供的方法来获取对应的 DOM 对象

② 利用 DOM 树的节点关系来访问

(2)使用 document 对象的方法来访问,window 对象的 document 对象提供了如下的方法来找到 HTML 元素(DOM对象)

① document.getElementById(idVal):根据HTML元素的id值来找到该DOM对象。

② document.getElementsByName(name):根据HTML元素的name属性来找到该DOM对象的集合。

③ document.getElementsByClassName(className):根据HTML元素的class名称找到该DOM对象的集合

④ document.getElementsByTagName(tagName):根据HTML元素的标签名找到该DOM对象的集合

⑤ document.querySelector(CSS选择器):通过CSS选择器返回DOM对象

示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo34</title>
</head>
<body>
  <div id="mdiv" style="border: 1px solid #ccc;"></div>
  <input type="text" name="info" id="info">
  <p id="mp">一个段落</p>
  <script>
    //找到 id=mdiv 的 dom 对象
    let mdiv = document.getElementById("mdiv");
    //设置 dom 对象的属性
    /**
     * dom 对象常用属性:
     * innerHTML:获取或设置 dom 对象内部的 HTML 片段
     * innerText:获取或设置 dom 对象内部的文本内容
     */
    mdiv.innerHTML = "<h1>新增的h1标签</h1>";
    //mdiv.innerText = "<h1>新增的h1标签</h1>";
    //找到 info 这个 dom
    var info = document.getElementById("info");
    //设置 info 对象的 value 属性:
    info.value = "我是通过 js 代码设置的 value 值";
    /**
     * 我们除了可以使用 dom 对象的原生属性之外,还可以通过 dom.setAttribute(属性名, 属性值) 来设置 dom 的属性值,通过
     * dom.getAttribute(属性名) 来获取 dom 对象的属性值,并且该方式可以设置自定义的属性
     */
    var mp = document.getElementById("mp");
    mp.innerText = "我是通过 js 添加的文本";
    //添加一个自定义属性
    //mp.test = "测试";
    mp.setAttribute("test","测试");
  </script>
</body>
</html>

(3)利用节点关系访问 HTML 元素

① Node parentNode:返回当前节点的父节点

② Node previousNode:返回当前节点的前一个兄弟节点

③ Node nextSibling:返回当前节点的下一个兄弟节点

④ Node[] childNodes:返回当前节点的所有孩子节点

⑤ Node firstChild:返回当前节点的第一个孩子节点

⑥ Node lastChild:返回当前节点的最后一个孩子节点

示例:

(4)节点的修改:这里的修改我们主要指对元素节点的操作。

① 创建节点:document.createElement(标签名)

② 删除节点:父节点.removeChild(子节点)

③ 替换节点:父节点.replaceChild(新节点 , 旧节点)

④ 插入节点

父节点.appendChild(子节点)

父节点.insertBefore(新节点 , 旧节点)

示例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>demo57</title>
</head>
<body>
<div class="mf">
  <!--javascript:void(0):禁用表单提交-->
  <form action="javascript:void(0)" id="mf">
    编号:<input type="text" name="id"> <br>
    姓名:<input type="text" name="name"> <br>
    年龄:<input type="text" name="age"> <br>
    性别:<input type="text" name="sex"> <br>
    工资:<input type="text" name="sal"> <br>
    <input type="submit" value="增加">
  </form>
</div>
<hr>
<div class="mt">
  <table border="1" cellspacing="0" cellpadding="0" id="mt">
    <thead>
      <tr>
        <th>编号</th>
        <th>姓名</th>
        <th>年龄</th>
        <th>性别</th>
        <th>工资</th>
        <th>操作</th>
      </tr>
    </thead>
    <tbody>

    </tbody>
  </table>
</div>
<script>
  var myform = document.getElementById("mf");
  var mytable = document.getElementById("mt");
  //表单的提交事件:当表单提交的时候,执行后面的匿名函数
  myform.onsubmit = function () {
    //找到所有的 input 元素
    let inputs = this.getElementsByTagName("input");
    var id = inputs[0].value;
    var name = inputs[1].value;
    var age = inputs[2].value;
    var sex = inputs[3].value;
    var sal = inputs[4].value;
    //通过表格对象找到 tbody 这个 dom 对象
    let tbody = mytable.querySelector("tbody");
    let tr = document.createElement("tr");//创建一个表格行
    //表格行内容指定 HTML 片段
    tr.innerHTML = "<td>"+id+"</td>" + "<td>"+name+"</td>" + "<td>"+age+"</td>" + "<td>"+sex+"</td>" +
            "<td>"+sal+"</td>" + "<td><a href='javascript:void(0)'>删除</a></td>";
    tbody.append(tr);//将包含了数据的表格行附加给 tbody 对象
    //找到了当前行的最后一个孩子的孩子:就是"删除"这个 a 标签,给其添加一个单击事件
    tr.lastChild.childNodes[0].onclick = function () {
      //this在这里指的就是发生单击事件的 a 标签
      this.parentNode.parentNode.remove();//将a的父元素的父元素 tr 本身删除
    }
  }
</script>
</body>
</html>

5.DOM 事件模型

(1)JavaScript 在浏览器中运行,浏览器中的 HTML 元素主要由 DOM 元素组成,这些 DOM 对象也会对应到各种 HTML 元素,我们可以为这些 DOM 对象添加事件处理函数,当某个 DOM 对象(HTML元素)发生对应的事件的时候,那么对应的事件函数就会自动被调用。

(2)HTML 元素的事件可以由事件属性来指定,事件属性是以事件类型加上一个 “on” 前缀来组成的,比如:onclick,onfocus 等等,这些属性名被称为事件处理器,属性值就是对应的事件处理函数,当事件发生时,对应的事件函数就自动被调用。

示例:

(3)绑定 DOM 对象的属性来绑定事件函数:

示例:找到某个 DOM 对象,给其事件属性指定事件函数

6.标准的 HTML 文档元素支持的事件:

示例1:变化表格的背景颜色

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo39</title>
  <style>
    *{
      margin: 0;
      padding: 0;
      text-align: center;
    }
    .wrap {
      width: 500px;
      margin: 100px auto 0;
    }
    table{
      border-collapse: collapse;/*单元格之间没有间距*/
      border-spacing: 0; /*单元格之间间距为0*/
      border: 1px solid #c0c0c0;
      width: 500px;
    }
    th,td{
      border: 1px solid #d0d0d0;
      color: #404060;
      padding: 10px;
    }
    th{
      background-color: #09c;
      font: bold 16px "微软雅黑";
      color: #fff;
    }
    tbody tr{
      background-color: #f0f0f0;
      cursor: pointer;
    }
    .current {
      background-color: red!important; /*不能继承父元素的颜色,必须为红色*/
    }
  </style>
</head>
<body>
  <div class="wrap">
    <table>
      <thead>
      <tr>
        <th>序号</th>
        <th>姓名</th>
        <th>课程</th>
        <th>成绩</th>
      </tr>
      </thead>
      <tbody id="target">
        <tr>
          <td>1</td>
          <td>吕不韦</td>
          <td>语文</td>
          <td>100</td>
        </tr>
        <tr>
          <td>2</td>
          <td>吕布</td>
          <td>日语</td>
          <td>100</td>
        </tr>
        <tr>
          <td>3</td>
          <td>吕蒙</td>
          <td>营销学</td>
          <td>100</td>
        </tr>
        <tr>
          <td>4</td>
          <td>吕尚</td>
          <td>数学</td>
          <td>100</td>
        </tr>
        <tr>
          <td>5</td>
          <td>吕雉</td>
          <td>英语</td>
          <td>100</td>
        </tr>
        <tr>
          <td>6</td>
          <td>吕超</td>
          <td>体育</td>
          <td>100</td>
        </tr>
      </tbody>
    </table>
  </div>
  <script>
    //各行变色
    var tbody = document.getElementById("target");
    var trArr = tbody.children;//找到 tbody 的所有孩子,即所有的 tr,不包含 td
    for (let i = 0; i < trArr.length; i++) {
      if(i % 2 == 0){
        trArr[i].style.backgroundColor = "#a3a3a3";
      }else {
        trArr[i].style.backgroundColor = "#ccc";
      }

      //鼠标进入 tr 的时候高亮,离开后正常
      var color = "";
      //鼠标悬停修改 tr 背景色
      trArr[i].onmouseover = function () { //给所有的 tr 绑定鼠标悬停事件
        //在赋值之前,先记录原来的颜色
        color = this.style.backgroundColor;//this 在这里指的是发生该事件的对象 tr
        //将发生事件的 tr 的颜色修改
        this.style.backgroundColor = "#fff";
      }
      //鼠标移出去的时候恢复原来的颜色
      trArr[i].onmouseout = function () {
        this.style.backgroundColor = color;
      }
    }
  </script>
</body>
</html>

示例2:将左边 select 下拉框选中的元素移动到右边的 select 下拉框中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo40</title>
  <style>
    select{
      width: 170px;
      height: 200px;
      font-size: 16px;
      background-color: #a4ff43;
    }
  </style>
</head>
<body>
  <select name="sel1" id="sel1" size="10" multiple>
    <option value="0">香蕉</option>
    <option value="1">苹果</option>
    <option value="2">鸭梨</option>
    <option value="3">葡萄</option>
  </select>
  <button>>>></button>
  <button><<<</button>
  <button>></button>
  <button><</button>
  <select name="sel2" id="sel2" size="10" multiple>

  </select>
  <script>
    //需求1:点击 <<< 和 >>> 按钮时,所有的子元素跑到对方标签中
    var sel1 = document.getElementById("sel1");
    var sel2 = document.getElementById("sel2");
    var btnArr = document.getElementsByTagName("button");
    btnArr[0].onclick = function () { //第一个按钮 >>>
      //获取所有 sel1 的元素,整体添加到 sel2 中
      var arr = sel1.children;
      for (let i = arr.length - 1;i >= 0; i--){
        sel2.appendChild(arr[i]);
      }
    }
    //同理,全部过来
    btnArr[1].onclick = function () { //第二个按钮 <<<
      //获取所有 sel2 的元素,整体添加到 sel1 中
      var arr = sel2.children;
      for (let i = arr.length - 1;i >= 0; i--){
        sel1.appendChild(arr[i]);
      }
    }
    //需求2:点击 > 和 < 按钮时,选中的元素跑到对方,提示:option 有一个属性 selected,如果为 true,表示选中
    btnArr[2].onclick = function () { //第三个按钮 >
      //获取所有 sel1 的元素,选中的添加到 sel2 中
      var arr = sel1.children;
      for (let i = arr.length - 1;i >= 0; i--){
        if (arr[i].selected === true)
          sel2.appendChild(arr[i]);
      }
    }
    btnArr[3].onclick = function () { //第四个按钮 <
      //获取所有 sel2 的元素,选中的添加到 sel1 中
      var arr = sel2.children;
      for (let i = arr.length - 1;i >= 0; i--){
        if (arr[i].selected === true)
          sel1.appendChild(arr[i]);
      }
    }
  </script>
</body>
</html>

7.DOM 事件模型

(1)DOM 也提供了事件模型:

通过 addEventListener(‘eventType’,handler,captureFlag) 方法监听事件,其中 ’eventType’ 表示事件的名称,就是属性事件去掉 on 即可,handler 是事件函数,事件发生时触发,captureFlag 表示监听事件的阶段,true 表示捕获阶段,false 表示冒泡阶段,默认是 false。

示例:

(2)当事件发生时,会自动创建一个 Event 事件对象,并传递给事件函数作为参数,Event 接口中主要定义了如下属性:

① type:返回事件的类型,比如 click,mouseover 等等

② target:触发事件的事件源

③ currentTarget:返回事件当前所在的事件源

④ button:返回一个数字,代表出发事件的鼠标键,0 表示左键,1 表示中键,2 表示右键

⑤ altKey,ctrlKey,metaKey,shiftKey:分别代表事件发生时是否同时按下了alt,ctrl,meta,shift 键

⑥ clientX,clientY:返回事件发生时的鼠标的位置,以浏览器窗口为坐标系

⑦ screenX,screenY:返回事件发生时的鼠标的位置,以显示器为坐标系

⑧ offsetX,offsetY:返回事件发生时的鼠标的位置,以父元素作为坐标系

示例:

(3)事件传播

DOM 事件发生之后,会进行传播,会经历两个阶段,第一个阶段称为事件捕获阶段,事件从最顶层元素依次往下传播,直到传播到最底层元素,接着进入第二个阶段:事件冒泡阶段,事件传播从底层依次上溯,直到达到顶层的元素为止,如下图:

监听事件的函数 addEventListener() 方法的第三个参数可以指定是去监听捕获阶段(true),还是监听冒泡阶段(false,默认)。为了阻止事件传播,可以使用 Event 对象的 stopPropagation() 方法来阻止事件传播。

示例1:监听冒泡阶段(默认情况)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo43</title>
  <style>
    *{
      margin: 0;
      padding: 0;
    }
    .p{
      width: 400px;
      height: 400px;
      background-color: blue;
    }
    .s{
      width: 300px;
      height: 300px;
      background-color: red;
    }
    .ss{
      width: 200px;
      height: 200px;
      background-color: yellow;
    }
  </style>
</head>
<body>
  <div class="p">
    父 DIV
    <div class="s">
      儿子 DIV
      <div class="ss">
        孙子 DIV
      </div>
    </div>
  </div>
  <script>
    var p = document.querySelector(".p");//父元素
    var s = document.querySelector(".s");//子元素
    var ss = document.querySelector(".ss");//孙子子元素
    //addEventListener 默认情况下就是监听冒泡阶段
    p.addEventListener("click",function () {
      console.log("父元素被点击");
    });
    s.addEventListener("click",function () {
      console.log("子元素被点击");
    });
    ss.addEventListener("click",function () {
      console.log("孙子元素被点击");
    });
  </script>
</body>
</html>

从执行的结果可知,冒泡阶段事件传播的顺序是:孙子元素被点,然后是儿子元素,最后是父元素

示例2:监听捕获阶段

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo43</title>
  <style>
    *{
      margin: 0;
      padding: 0;
    }
    .p{
      width: 400px;
      height: 400px;
      background-color: blue;
    }
    .s{
      width: 300px;
      height: 300px;
      background-color: red;
    }
    .ss{
      width: 200px;
      height: 200px;
      background-color: yellow;
    }
  </style>
</head>
<body>
  <div class="p">
    父 DIV
    <div class="s">
      儿子 DIV
      <div class="ss">
        孙子 DIV
      </div>
    </div>
  </div>
  <script>
    var p = document.querySelector(".p");//父元素
    var s = document.querySelector(".s");//子元素
    var ss = document.querySelector(".ss");//孙子子元素
    //addEventListener 第三个参数为 true 就是监听捕获阶段
    p.addEventListener("click",function () {
      console.log("父元素被点击");
    },true);
    s.addEventListener("click",function () {
      console.log("子元素被点击");
    },true);
    ss.addEventListener("click",function () {
      console.log("孙子元素被点击");
    },true);
  </script>
</body>
</html>

监听捕获阶段,事件传播的顺序:父元素,然后子元素,最后孙子元素

示例3:阻止事件传播:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo43</title>
  <style>
    *{
      margin: 0;
      padding: 0;
    }
    .p{
      width: 400px;
      height: 400px;
      background-color: blue;
    }
    .s{
      width: 300px;
      height: 300px;
      background-color: red;
    }
    .ss{
      width: 200px;
      height: 200px;
      background-color: yellow;
    }
  </style>
</head>
<body>
  <div class="p">
    父 DIV
    <div class="s">
      儿子 DIV
      <div class="ss">
        孙子 DIV
      </div>
    </div>
  </div>
  <script>
    var p = document.querySelector(".p");//父元素
    var s = document.querySelector(".s");//子元素
    var ss = document.querySelector(".ss");//孙子子元素
    //addEventListener 默认就是监听冒泡阶段
    p.addEventListener("click",function () {
      console.log("父元素被点击");
    });
    s.addEventListener("click",function () {
      console.log("子元素被点击");
    });
    ss.addEventListener("click",function (e) {//e 就是 Event 对象
      console.log("孙子元素被点击");
      e.stopPropagation();//阻止事件传播
    });
  </script>
</body>
</html>

可以发现,当我们点击孙子元素时,只有孙子元素响应了事件,事件被阻止了,没有继续往上传播。

综合案例:祝愿墙

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>祝愿墙</title>
  <style>
    body {
      margin: 0 auto;
      padding: 0px;
      font-size: 12px;
      background: url("images/bg.gif") repeat center 36px;
      text-align: center;
      background-color: #c30230;
    }
    #content {
      margin: 0 auto;
      width: 960px;
      background: url("images/content_bg.jpg") no-repeat left top;
      height: 627px;
      position: relative;
    }
    #content .tip0, #content .tip1, #content .tip2, #content .tip3, #content .tip4, #content .tip5, #content .tip6, #content .tip7, #content .tip8 {
      position: absolute;
      width: 227px;
      left: 200px;
      top: 100px;
    }
    #content .tip_h {
      background: url("images/tip1_h.gif") no-repeat left top;
      width: 227px;
      padding-top: 45px;
      height: 23px;
      text-align: left;
      cursor: move;
    }

    #content .tip_c {
      background: url("images/tip1_c.gif") repeat-y;
      width: 200px;
      padding-left: 12px;
      padding-right: 15px;
      min-height: 40px;
      text-align: left;
      line-height: 20px;
      max-height: 160px;
      word-wrap: break-word; /*强制长单词在其容器宽度不足时自动换行*/
      word-break: break-all; /*允许在单词内换行*/
      overflow: hidden;
    }
    #content .tip_f {
      background: url("images/tip1_f.gif") no-repeat left top;
      width: 227px;
      height: 53px;
      padding-top: 20px;
    }
    #content .num {
      float: left;
      padding-left: 7px;
      width: 195px;
    }
    #content .close {
      float: left;
      font-size: 12px;
      cursor: pointer;
      color: #000000;
    }
    .clr {
      clear: both;
      overflow: auto;
      display: block;
      height: 0px;
    }
    #content .icon {
      float: left;
      width: 35px;
      padding-left: 15px;
      height: 35px;
      text-align: center;
    }
    #content .name {
      float: right;
      padding-right: 15px;
      text-align: right;
      font-size: 14px;
      line-height: 35px;
      color: #C0F;
    }

  </style>
</head>
<body>
  <!--纸条墙-->
  <div id="content">
  </div>
<script>
  //模拟数据库,获取信息
  var messages = [
    {"id":1,"name":"mahu","content":"今天你拿苹果支付了么","time":"2016-02-17 00:00:00"},
    {"id":2,"name":"haha","content":"今天天气不错,风和日丽的","time":"2016-02-18 12:40:00"},
    {"id":3,"name":"jjjj","content":"常要说的事儿是乐生于苦","time":"2016-03-18 12:40:00"},
    {"id":4,"name":"9.8的妹纸","content":"把朋友家厕所拉堵了 不敢出去 掏了半小时了都","time":"2016-03-18 12:40:00"},
    {"id":5,"name":"雷锋ii.","content":"元宵节快乐","time":"2016-02-22 12:40:00"},
    {"id":6,"name":"哎呦哥哥.","content":"据说今晚央视的元宵晚会导演和春晚导演是同一个人,真是躲得过初一,躲不过十五。","time":"2016-02-22 01:30:00"},
    {"id":7,"name":"没猴哥,不春晚","content":"班主任:“小明,你都十二岁了,还是三年级,不觉得羞愧吗”?。小明:“一点也不觉得,老师你都四十多岁了,不也是年年在三年级混日子吗?羞愧的应该是你”。老师:……","time":"2016-02-22 01:30:00"},
    {"id":8,"name":"哎呦杰杰.","content":"真搞不懂你们地球人,月亮有什么好看的,全是坑,还是对面那哥们好看,","time":"2016-02-22 01:30:00"},
    {"id":9,"name":"哎呦哎呦","content":"今天哪里的烟花最好看!!?答:朋友圈。。。","time":"2016-02-22 02:30:00"}
  ];

  //需求1:模拟数据库获取信息,然后在页面上生成数组的长度个tip,然后分别填充内容。
  //需求2:点击内容,提高层级;点击关闭按钮,删除tip标签;双击顶部,删除标签.....

  //步骤:
  //获取相关元素
  var content = document.getElementById("content");
  //循环生成div标签,然后为innerHTML属性添加内容
  for(var i=0;i<messages.length;i++){
    //生成新标签
    var newDiv = document.createElement("div");
    //绑定类名和ID
    newDiv.className = "tip" + i;
    newDiv.id = "tip" + messages[i].id;
    //改变位置
    var topValue = parseInt(Math.random()*400);
    var leftValue = parseInt(Math.random()*700);
    newDiv.style.top = topValue+"px";
    newDiv.style.left = leftValue+"px";
    //赋值内容
    newDiv.innerHTML = '<div class="tip_h" title="双击关闭纸条">'+
            '<div class="num">第[49568]条 '+messages[i].time+'</div>'+
            '<div class="close" title="关闭纸条" >×</div>'+
            '<div class="clr"></div>'+
            '</div>'+
            '<div class="tip_c">'+
            messages[i].content +
            '</div>'+
            '<div class="tip_f">'+
            '<div class="icon">'+
            '<img src="images/bpic_1.gif" alt="" title="">'+
            '</div>'+
            '<div class="name">'+messages[i].name+'</div>'+
            '<div class="clr"></div>'+
            '</div>';
    //把新创建的元素放入content里面
    content.appendChild(newDiv);

    //绑定事件,提高层级
    var index = 1;
    newDiv.onclick = function () {
      this.style.zIndex = index;
      index++;
    };

    //点击关闭按钮的时候关闭父盒子。
    var closeDiv = newDiv.getElementsByClassName("close")[0];
    closeDiv.onclick = function () {
      //this就是 close这个div
      content.removeChild(this.parentNode.parentNode);
    }

    //双击关闭按钮类名叫做tip_h
    var dbDiv = newDiv.getElementsByClassName("tip_h")[0];
    dbDiv.ondblclick = function () {
      //this 就是值 tip_h
      content.removeChild(this.parentNode);
    }

  }
</script>
</body>
</html>

九、AJAX

1、AJAX概述

(1)什么是Ajax ?

AJAX(Asynchronous JavaScript and XML)是一种能够让前端网页和后台Web服务器进行异步交互的技术,可以实现页面局部刷新(可以不用去加载整个页面而实现页面的局部刷新)。AJAX 的主要作用是让网页能与服务端进行数据异步交互,我们能够使用 HTML+AJAX 能够代替 JSP,实现网页上数据的动态展示。

(2)什么是异步交互?

异步交互是指能够让客户端发送一个请求后,不需要等待服务端的结果的返回,随时能够再次发送下一个请求。网页能够局部刷新就是利用了异步交互技术。而同步交互需要等待服务端响应数据后,才能发送下一个请求,所以使用同步交互的网页需要手动刷新。

(3)AJAX的优点:

        1)提高网页的动态性。AJAX技术能让网页实现局部刷新,能够极大提高网页的动态性

        2)提高用户体验。Ajax技术是一种异步交互技术,用户浏览器不必等待请求结果就能再次发送请求,大大提高用户体验,同时能够为用户提供搜索提示,验证提示

        3)AJAX可使网页小程序更小、更快,更友好

2. 核心对象

XMLHttpRequest,AJAX 的所有操作都是通过该对象进行的

使用步骤:

(1)创建 XMLHttpRequest 对象

        var xhr = new XMLHttpRequest();

(2)设置请求信息

        //method表示请求后台服务器的方式:get或post等等方式,url:请求后台服务器的地址

        xhr.open(method, url); //打开与后台服务器的连接

(3)发送请求

        xhr.send(body)//get请求不传body参数,只有 post 请求要传 body

(4)接收响应

3. AJAX 快速入门:

(1)后台服务器:

基于 Servlet 的 Web 应用程序:Servlet 是部署在 HTTP 服务器(Tomcat服务器)的一个组件,专门用于响应用户的请求。

1)创建 JavaWeb 项目:

上面配置好的 Tomcat 是这样配置的

然后点击“下一步”:

然后点击“Finish”就生成后台 Web 工程了,如下:

2)导入 gson.jar 包:

将后台的数据转换成前端能够接受的 JSON 数据,因为我们前后端交互使用 JSON 对象进行交互

a. WEB-INF 目录下新建 lib 目录,将 gson.jar 拷贝进去

b. 右键 lib 目录,将整个 lib 目录中的 jar 包添加为工程的库:Add As Library

3) 创建前后交互的 JavaBean:User

4) 创建后台组件 Servlet,跟前端进行交互

package com.edu.ctrl;

import com.edu.beans.User;
import com.google.gson.Gson;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

@WebServlet("/userServlet") //该 Servlet 的后台 URL 地址
public class UserServlet extends HttpServlet {
    //用于响应客户端的 GET 请求
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置请求和响应的字符编码为 UTF-8,保证通讯过程中可以使用中文
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        //准备回送给客户端的数据
        List<User> users = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            users.add(new User(i, "姓名" + i, 20 + i, i%2==0?"男":"女"));
        }
        //产生 gson 对象,使用 gson 将 users 对象转换为 json 格式的字符串,发送给前端
        Gson gson = new Gson();
        String s = gson.toJson(users);//将 users 对象转换为 json 格式的字符串
        PrintWriter out = response.getWriter();
        out.write(s);//将 json 字符串写给客户端
        out.flush();//刷新流
    }
    //用于响应客户端的 POST 请求
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

(2) 在工程的 webapp 目录下创建前端页面 index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
  <table border="1" cellspacing="0" cellpadding="0">
    <thead>
      <tr>
        <th>编号</th>
        <th>姓名</th>
        <th>年龄</th>
        <th>性别</th>
        <th>操作</th>
      </tr>
    </thead>
    <tbody>
      
    </tbody>
  </table>
  <script>
    //1. 创建 XMLHttpRequest 对象
    var xhr = new XMLHttpRequest();
    //2. 发送请求
    //2.1 确定请求方式和请求后台的地址
    xhr.open("GET","userServlet");
    //2.2 发送请求到后台
    xhr.send();
    //3. 获取后台响应数据
    xhr.onreadystatechange = function () {
      //3.1 判断服务器端对于浏览器的请求是否响应完成,并判断客户端是否成功收到响应数据
      if(this.readyState == 4 && this.status == 200){
        //将服务器发送过来的JSON字符串转换为JavaScript的JSON对象
        let users = JSON.parse(this.responseText);//得到的 users 是一个 json 对象组成数组
        var content = "";
        for (let i = 0; i < users.length; i++) {
          content += "<tr>";//行
          content += "<td>" + users[i].id + "</td>" +
                  "<td>" + users[i].name + "</td>" +
                  "<td>" + users[i].age + "</td>" +
                  "<td>" + users[i].sex + "</td>" +
                  "<td><a href=''>删除</a><a href=''>更新</a></td>";
          content += "</tr>";
        }
      }
      var tbody = document.querySelector("table tbody");
      tbody.innerHTML = content;
    }
  </script>
</body>
</html>

(3) 部署 Web 应用程序到 Tomcat 服务器中运行:

然后部署应用:

然后点击启动按钮启动 Tomcat 服务器:

结果:

我们实现的是局部刷新,JS 代码只改动了表格的 tbody 部分,其他地方没有变,是属于异步的通讯方式,效率极高。


网站公告

今日签到

点亮在社区的每一天
去签到