## Day02 JavaScript、Vue3

---

### 1. JavaScript

##### Web标准及其组成
* Web标准也称网页标准，由一系列的标准组成，大部分由W3C（World Wide Web Consortium，万维网联盟）负责制定。
*  三个组成部分：
  * HTML：负责网页的结构（页面元素和内容）。
  * CSS：负责网页的表现（页面元素的外观、位置等页面样式，如：颜色、大小等）。
  * JavaScript：负责网页的行为（交互效果）。

  <figure><img src="/AiJavaWeb/imgs/jwai02-01.png"><figcaption>图1 Web标准组成</figcaption></figure>

##### JavaScript及其组成

* JavaScript（简称：JS） 是一门跨平台、面向对象的脚本语言，是用来控制网页行为，实现页面的交互效果。JavaScript 和 Java 是完全不同的语言，不论是概念还是设计。但是基础语法类似。
* 组成：
  * ECMAScript: 规定了JS基础语法核心知识，包括变量、数据类型、流程控制、函数、对象等。
  * BOM：浏览器对象模型，用于操作浏览器本身，如：页面弹窗、地址栏操作、关闭窗口等。
  * DOM：文档对象模型，用于操作HTML文档，如：改变标签内的内容、改变标签内字体样式等。 



ECMA： ECMA国际（前身为欧洲计算机制造商协会），制定了标准化的脚本程序设计语言 ECMAScript，这种语言得到广泛应用。而JavaScript是遵守ECMAScript的标准的（ES2024是最新版本）

<figure><img src="/AiJavaWeb/imgs/jwai02-02.png"><figcaption>图2 JavaScript组成</figcaption></figure>

#### 1.1 JS 核心语法

##### 1.1.1 引入方式

##### ① 内部脚本

内部脚本：将JS代码定义在HTML页面中

* JavaScript代码必须位于 ```<script></script>``` 标签之间
* 在HTML文档中，可以在任意地方，放置任意数量的 ```<script>```
* 一般会把脚本置于 ```<body> ```元素的底部，可改善显示速度

##### ② 外部脚本

外部脚本：将 JS代码定义在外部 JS文件中，然后引入到HTML页面中

##### 01. JS-引入方式.html

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>JS-引入方式</title>
</head>
<body>
  <h1>JS-引入方式(杜老师)</h1>
  <hr>
  <p>JS-引入方式有两种：内部脚本和外部脚本</p>
  <p>内部脚本：在HTML页面中，使用&lt;script>标签嵌入JS代码</p>
  <p>外部脚本：将JS代码写在独立的JS文件中，然后在HTML页面中引入</p>
  <p>外部脚本的优势：</p>
  <ul>
    <li>可以将JS代码写在独立的文件中，方便维护</li>
    <li>可以在多个HTML页面中引入同一个JS文件，避免重复代码</li>
  </ul>
  <p>外部脚本的劣势：</p>
  <ul>
    <li>引入外部脚本需要额外的HTTP请求，影响页面加载速度</li>
  </ul>

  <script>
    //1. 内部脚本
    alert('内部脚本(杜老师)：Hello JS');
  </script>

  <!-- 2. 外部脚本 -->
  <script src="js/demo.js" charset="UTF-8"></script>

</body>
</html>
```

##### js/demo.js

```javascript
alert('外部引入脚本（杜老师）：Hello JavaScript');
```

<figure><img src="/AiJavaWeb/imgs/jwai02-03.png"><figcaption>图3 js引入方式</figcaption></figure>



##### 1.1.2 基础语法

##### ① 变量&常量

* JS中用 <mark>let</mark> 关键字来声明变量 (<mark>弱类型</mark>语言，变量可以存放不同类型的值)。
* 变量名需要遵循如下规则：
  * 只能用 字母、数字、下划线（_）、美元符号（$）组成，且数字不能开头
  * 变量名严格区分大小写，如 name 和 Name 是不同的变量
  * 不能使用关键字，如：let、var、if、for等



* JS中用 <mark>const</mark> 关键字来声明<mark>常量</mark> 。
* 一旦声明，常量的值就不能改变（不可以重新赋值）。

##### 02. JS-基础语法.html

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>JS-基础语法</title>
</head>
<body>
  <h1>JS-基础语法--变量与常量的声明和赋值(杜老师)</h1>
  <hr>
  <p>变量：可以变化的量，在程序运行过程中，其值可以发生改变的量。</p>
  <p>常量：不变的量，在程序运行过程中，其值不能发生改变的量。</p>

  <p>JS-基础语法有以下几个方面：</p>
  <ul style="display: flex; justify-content: space-around;">
    <li>变量</li>
    <li>常量</li>
    <li>数据类型</li>
    <li>运算符</li>
    <li>流程控制</li>
    <li>函数</li>
    <li>对象</li>
    <li>数组</li>
    <li>字符串</li>
    <li>日期</li>
    <li>正则表达式</li>
    <li>JSON</li>
  </ul>
  <p>JS-基础语法的详细内容，请参考：<a href="https://www.runoob.com/js/js-tutorial.html">JS-基础语法</a></p>
  <p>F12-控制台-查看: 声明变量、常量和输出</p>

  <script>
    //1. 声明变量
    let a = 10;
    console.log("a:10 a = ", a);
    a = "Hello";
    console.log("a:Hello a = ", a); 
    a = true;
    console.log("a:true = ", a);
    console.log("a的类型 = ", typeof a);

    //2. 声明常量
    const PI = 3.14;
    //PI = 5.0;

    console.log("PI=", PI); //输出到控制台
    alert(a); //弹出框
    PI = 5.0;
    // document.write(PI); //输出到body区域(不常用)
  </script>
</body>
</html>
```

<figure><img src="/AiJavaWeb/imgs/jwai02-04.png"><figcaption>图4 变量与常量</figcaption></figure>



##### ② 数据类型

* JavaScript的数据类型分为：基本数据类型和引用数据类型（对象）。
* 基本数据类型：
  * <mark>number</mark>：数字（整数、小数、NaN(Not a Number)）
  * <mark>boolean</mark>：布尔。true，false
  * <mark>null</mark>：对象为空。JavaScript是大小写敏感的，因此null、Null、NULL是完全不同的
  * <mark>undefined</mark>：当声明的变量未初始化时，该变量的默认值是 undefined
  * <mark>string</mark>：字符串，单引号、双引号、反引号皆可，推荐使用<mark>单引号</mark>
  * 使用 <mark>typeof </mark>运算符可以获取数据类型：



模板字符串语法：

* `(反引号，英文输入模式下按键盘的tab键上方波浪线 ~ 那个键）
* 内容拼接变量时，使用 ${} 包住变量

```html
<script>
   let name = 'Tom';
   let age = 18;
   console.log('大家好, 我是新入职的' + name + ', 今年' + age + '岁了, 请多多关照');
   console.log(`大家好, 我是新入职的${name}, 今年${age}岁了, 请多多关照`);
</script>
```

##### 03. JS-数据类型.html

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>JS-数据类型</title>
</head>
<body>
  <h1>JS-数据类型(杜老师)</h1>
  <hr>
  <p>F12打开控制台查看结果</p>

  <script>
    //1. 数据类型
    console.log("10的类型:",typeof 10); //number
    console.log("1.5的类型:",typeof 1.5); //number

    console.log("true的类型:",typeof true); //boolean
    console.log("false的类型:",typeof false); //boolean

    console.log("'Hello'的类型:",typeof "Hello"); //string
    console.log("'JS'的类型:",typeof 'JS'); //string
    console.log("`JavaScript`的类型:",typeof `JavaScript`); //string

    console.log("null的类型:",typeof null); //null ? -> object

    let a ;
    alert(typeof a); //undefined

    //2. 模板字符串 - 简化字符串拼接
    let name = '杜老师';

    let age = 18;

    console.log('我是'+name+', 我今年'+age+'岁');
    console.log(`我是${name}, 我今年${age}岁`);
    console.log(`我是${name}, 我今年${age+1}岁`);
    
  </script>
</body>
</html>
```

<figure><img src="/AiJavaWeb/imgs/jwai02-05.png"><figcaption>图5 数据类型</figcaption></figure>



##### ③ 函数

* 介绍：函数（ function ）是被设计用来执行特定任务的代码块，方便程序的<mark>封装复用</mark>。
* 定义：JavaScript中的函数通过function关键字进行定义，语法为：

```javascript
function 函数名称(参数1, 参数2, ...){
    // 要执行的代码    
}
```

* 调用：函数名称(实际参数列表)
* 注意：<mark>由于JS是弱类型语言，形参、返回值都不需要指定类型。在调用函数时，实参个数与形参个数可以不一致，但是建议一致</mark>。  



##### 匿名函数

* 匿名函数是指一种没有名称的函数，可以通过两种方式定义：函数表达式 和 箭头函数。
* 匿名函数定义后，可以通过<mark>变量名</mark>直接调用。

<figure><img src="/AiJavaWeb/imgs/jwai02-06.png"><figcaption>图6 匿名函数的定义与调用</figcaption></figure>



##### 04. JS-函数.html

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>JS-函数</title>
</head>
<body>
  <h1>JS-函数(杜老师)</h1>
  <hr>
  <p>函数：一段可以重复调用的代码块。</p>
  <p>函数的分类：</p>
  <ul>
    <li>具名函数</li>
    <li>匿名函数</li>
    <li>箭头函数</li>
  </ul>
  <p>函数的定义与调用></p>
  <p>F12打开控制台查看结果</p>

  <script>
    //1. 函数定义及调用 - 具名函数
    function add1(a,b){
      return a + b;
    }

    let result = add1(10,20);
    console.log("具名函数: add1(10,20)=",result);
    result = add1(10,20,59);
    console.log("具名函数: add1(10,20,50)=",result);
    

    //2. 函数定义及调用 - 匿名函数
    //2.1 函数表达式
    let add2 = function(a,b){
      return a + b;
    }

    result = add2(2100,200);
    console.log("匿名函数: add2(2100,200)=",result);


    //2.2 箭头函数
    let add3 = (a,b) => {
      return a + b;
    }

    lresult = add3(1000,2000);
    console.log("箭头函数: add3(1000,2000)=",result);
  </script>
</body>
</html>
```

<figure><img src="/AiJavaWeb/imgs/jwai02-07.png"><figcaption>图7 函数小结</figcaption></figure>



##### ④ 自定义对象 

<mark>自定义对象是对前面所讲的变量、类型、函数的综合应用</mark>

<figure><img src="/AiJavaWeb/imgs/jwai02-08.png"><figcaption>图8 自定义对象</figcaption></figure>

<figure><img src="/AiJavaWeb/imgs/jwai02-09.png"><figcaption>图9 自定义对象小结</figcaption></figure>

##### json

* 概念：JavaScript Object Notation，JavaScript对象标记法 (JS对象标记法书写的<mark>文本</mark> ) 。
* 由于其语法简单，层次结构鲜明，现多用于作为<mark>数据载体</mark>，在网络中进行数据传输(代替ajax中xml格式)。

<figure><img src="/AiJavaWeb/imgs/jwai02-10.png"><figcaption>图10 JS对象与JSON格式的字符串</figcaption></figure>

##### 05. JS-自定义对象.html

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>JS-自定义对象</title>
</head>
<body>
  <h1>JS-自定义对象(杜老师)</h1>
  <hr>
  <p>自定义对象：由开发人员自定义的对象，用于存储和组织数据。</p>
  <p>自定义对象的定义格式：</p>
  <pre>
    let 对象名 = {
      属性名1: 属性值1,
      属性名2: 属性值2,
      ...
      方法名: function(){
        //方法体
      }
    }
  </pre>
  <p>自定义对象的使用格式：</p>
  <pre>
    对象名.属性名
    对象名.方法名()
  </pre>
  <p>F12控制台查看对象</p>

  <script>
    //1. 自定义对象
    let user1 = {
      name: '汤姆1',
      age: 18,
      gender: '男',
      sing: function(){ //注意: 在普通函数中, this指向当前对象 【推荐】
        console.log(this.name + '悠悠的唱着最炫的民族风~')
      }
    }
    console.log(user1.name);
    user1.sing();

    let user2 = {
     name: '汤姆2',
     age: 18,
     gender: '男',
     sing(){
      console.log(this.name + '悠悠的唱着最炫的民族风~')
     }
    }
    console.log(user2.name);
    user2.sing();

    let user3 = {
      name: '汤姆3',
      age: 18,
      gender: '男',
      sing: () => { //注意: 在箭头函数中, this并不指向当前对象 - 指向的是当前对象的父级 【不推荐】
        console.log(this + ':悠悠的唱着最炫的民族风~')
      }
    }

    console.log(user3.name);
    user3.sing();
 
    //2. JSON - JS对象标记法
    let person = {
      name: 'itcast',
      age: 18,
      gender: '男'
    }
    console.log("JSON对象:",person); 
    console.log("JSON对象转字符串:",JSON.stringify(person)); //js对象 --> json字符串

    let personJson = '{"name": "黑马", "age": 18}';
    console.log("字符串:",personJson);
    console.log("字符串转JSON对象:",JSON.parse(personJson)); //json字符串 --> js对象
    console.log("字符串转JSON对象.name:",JSON.parse(personJson).name);

  </script>
</body>
</html>
```

<figure><img src="/AiJavaWeb/imgs/jwai02-11.png"><figcaption>图11 JSON格式字符串</figcaption></figure>



##### 1.1.3 DOM

* 概念：Document Object Model，文档对象模型。

* 将标记语言的各个组成部分封装为对应的对象：

  * Document：整个文档对象
  * Element：元素对象
  * Attribute：属性对象
  * Text：文本对象
  * Comment：注释对象

* JavaScript 通过DOM，就能够对HTML进行操作：

  * 改变 HTML 元素的内容
  * 改变 HTML 元素的样式（CSS）
  * 对 HTML DOM 事件作出反应
  * 添加和删除 HTML 元素

  

  <figure><img src="/AiJavaWeb/imgs/jwai02-12.png"><figcaption>图12 DOM</figcaption></figure>

  

##### DOM操作

* DOM操作核心思想：将网页中所有的元素当做对象来处理。（标签的所有属性在该对象上都可以找到）
* 操作步骤：
  * 获取要操作的DOM元素对象
  * 操作DOM对象的属性或方法（查文档或AI）
* 获取DOM对象
  * 根据CSS选择器来获取DOM元素，获取匹配到的第一个元素：document.querySelector('选择器')
  * 根据CSS选择器来获取DOM元素，获取匹配到的所有元素： document.querySelectorAll('选择器')
*  注意：<mark>得到的是一个NodeList节点集合，是一个伪数组（有长度、有索引的数组）</mark>

##### 06. JS-DOM.html

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>JS-DOM常用操作</title>
</head>
<body>
  <h2>JS-DOM常用操作：获取元素和修改内容(杜老师)</h2>
  <hr>
  <p>F12打开控制台</p>
  <h1 id="title1">1111111</h1>
  <h1>22222</h1>
  <h1>33333</h1>

  <script>
    //1. 修改第一个h1标签中的文本内容
    //1.1 获取DOM对象
    let h1 = document.querySelector('#title1');
    let h2 = document.querySelector('h1'); // 获取第一个h1标签
    let hs = document.querySelectorAll('h1'); // 获取所有h1标签

    //1.2 调用DOM对象中属性或方法
    console.log(h1.innerText);
    h1.innerHTML = '修改后的文本内容';
    console.log(h2.innerText);
    h2.innerHTML = '第一个h1标签的文本内容';
    console.log(hs[1].innerText);
    hs[1].innerHTML = '222222修改后的文本内容';
  </script>
</body>
</html>
```



##### 案例：实现表格隔行换色效果

##### 07. JS-案例-员工列表.html

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Tlias智能学习辅助系统</title>
    <style>
        /* 导航栏样式 */
        .navbar {
            background-color: #b5b3b3; /* 灰色背景 */
            
            display: flex; /* flex弹性布局 */
            justify-content: space-between; /* 左右对齐 */

            padding: 10px; /* 内边距 */
            align-items: center; /* 垂直居中 */
        }
        .navbar h1 {
            margin: 0; /* 移除默认的上下外边距 */
            font-weight: bold; /* 加粗 */
            color: white;
            /* 设置字体为楷体 */
            font-family: "楷体";
        }
        .navbar a {
            color: white; /* 链接颜色为白色 */
            text-decoration: none; /* 移除下划线 */
        }

        /* 搜索表单样式 */
        .search-form {
            display: flex;
            flex-wrap: nowrap;
            align-items: center;
            gap: 10px; /* 控件之间的间距 */
            margin: 20px 0;
        }
        .search-form input[type="text"], .search-form select {
            padding: 5px; /* 输入框内边距 */
            width: 260px; /* 宽度 */
        }
        .search-form button {
            padding: 5px 15px; /* 按钮内边距 */
        }

        /* 表格样式 */
        table {
            width: 100%;
            border-collapse: collapse;
        }
        th, td {
            border: 1px solid #ddd; /* 边框 */
            padding: 8px; /* 单元格内边距 */
            text-align: center; /* 左对齐 */
        }
        th {
            background-color: #f2f2f2;
            font-weight: bold;
        }
        .avatar {
            width: 30px;
            height: 30px;
        }

        /* 页脚样式 */
        .footer {
            background-color: #b5b3b3; /* 灰色背景 */
            color: white; /* 白色文字 */
            text-align: center; /* 居中文本 */
            padding: 10px 0; /* 上下内边距 */
            margin-top: 30px;
        }

        #container {
            width: 80%; /* 宽度为80% */
            margin: 0 auto; /* 水平居中 */
        }
    </style>
</head>
<body>
    <h1>DOM操作</h1>
    <hr>
    <pre>
        1. 获取元素 document.querySelectorAll("tbody tr")
        2. 改变背景 trList[i].style.backgroundColor = 
    </pre>
    <div id="container">
        <!-- 顶部导航栏 -->
        <div class="navbar">
            <h1>Tlias智能学习辅助系统(杜老师)</h1>
            <a href="#">退出登录</a>
        </div>

        <!-- 搜索表单区域 -->
        <form class="search-form" action="/search" method="post">
            <label for="name">姓名：</label>
            <input type="text" id="name" name="name" placeholder="请输入姓名">

            <label for="gender">性别：</label>
            <select id="gender" name="gender">
                <option value=""></option>
                <option value="1">男</option>
                <option value="2">女</option>
            </select>

            <label for="position">职位：</label>
            <select id="position" name="position">
                <option value=""></option>
                <option value="1">班主任</option>
                <option value="2">讲师</option>
                <option value="3">学工主管</option>
                <option value="4">教研主管</option>
                <option value="5">咨询师</option>
            </select>

            <button type="submit">查询</button>
            <button type="reset">清空</button>
        </form>

        <!-- 表格展示区 -->
        <table>
            <!-- 表头 -->
            <thead>
                <tr>
                    <th>姓名</th>
                    <th>性别</th>
                    <th>头像</th>
                    <th>职位</th>
                    <th>入职日期</th>
                    <th>最后操作时间</th>
                    <th>操作</th>
                </tr>
            </thead>

            <!-- 表格主体内容 -->
            <tbody>
                <tr>
                    <td>令狐冲</td>
                    <td>男</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="令狐冲"></td>
                    <td>讲师</td>
                    <td>2021-06-15</td>
                    <td>2024-09-16 15:30</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>任盈盈</td>
                    <td>女</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="任盈盈"></td>
                    <td>咨询师</td>
                    <td>2021-07-20</td>
                    <td>2024-09-17 09:00</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>向问天</td>
                    <td>男</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>班主任</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>任我行</td>
                    <td>男</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>教研主管</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>田伯光</td>
                    <td>男</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="令狐冲"></td>
                    <td>班主任</td>
                    <td>2021-06-15</td>
                    <td>2024-09-16 15:30</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>不戒</td>
                    <td>女</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="任盈盈"></td>
                    <td>班主任</td>
                    <td>2021-07-20</td>
                    <td>2024-09-17 09:00</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>左冷禅</td>
                    <td>男</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>班主任</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>定逸</td>
                    <td>女</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>班主任</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>东方兄弟</td>
                    <td>男</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>讲师</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>金庸</td>
                    <td>男</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>咨询师</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
            </tbody>
        </table>

        <!-- 页脚版权区域 -->
        <footer class="footer">
            <p>江苏传智播客教育科技股份有限公司</p>
            <p>版权所有 Copyright 2006-2024 All Rights Reserved</p>
        </footer>
    </div>

    <script>
        //通过JS实现上述表格中数据行的隔行换色效果, 奇数行背景色设置为 #f2e2e2, 偶数行背景色设置为 #e6f7ff (JS新语法实现)
        let trList = document.querySelectorAll("tbody tr"); // 获取所有数据行 - DOM操作
        for (let i = 0; i < trList.length; i++) {
            if (i % 2 == 0) {
                trList[i].style.backgroundColor = "#f2e2e2";
            } else {
                trList[i].style.backgroundColor = "#e6f7ff";
            }
        }
    </script>

</body>
</html>
```

<figure><img src="/AiJavaWeb/imgs/jwai02-13.png"><figcaption>图13 DOM小结</figcaption></figure>



#### 1.2 JS 事件监听

##### 什么是事件？什么是事件监听？

* 事件：HTML事件是发生在HTML元素上的 "事情"。比如：
  * 按钮被点击
  * 鼠标移动到元素上
  * 按下键盘按键
* JavaScript可以在事件触发时，就立即调用一个函数做出响应，也称为 <mark>事件绑定或注册事件</mark>。

##### 事件监听

* 语法：事件源.addEventListener('事件类型', 事件触发执行的函数);
* 事件监听三要素
  * 事件源：哪个dom元素触发了事件，要获取dom元素
  * 事件类型：用什么方式触发，比如：鼠标单击 click
  * 事件触发执行的函数：要做什么事

<figure><img src="/AiJavaWeb/imgs/jwai02-14.png"><figcaption>图14 事件监听</figcaption></figure>

##### 08. JS-事件监听.html

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>JS事件</title>
</head>
<body>
  <h1>JS-事件监听(杜老师)</h1>
  <hr>
  <input type="button" id="btn1" value="点我一下试试1">
  <input type="button" id="btn2" value="点我一下试试2">

  <script>
    //事件监听 - addEventListener (可以多次绑定同一事件)
    document.querySelector('#btn1').addEventListener('click', () => {
      console.log('试试就试试~~');
    });
    document.querySelector('#btn1').addEventListener('click', () => {
      console.log('试试就试试22~~');
    });

    //事件绑定-早期写法 - onclick (如果多次绑定同一事件, 覆盖) - 了解
    document.querySelector('#btn2').onclick =  () => {
      console.log('试试就试试~~');
    }
    document.querySelector('#btn2').onclick =  () => {
      console.log('试试就试试22~~');
    }
  </script>
</body>
</html>
```

<figure><img src="/AiJavaWeb/imgs/jwai02-15.png"><figcaption>图15 事件监听小结</figcaption></figure>



##### 案例 实现表格数据行鼠标移入移出隔行换色效果。
需求：实现鼠标移入数据行时，背景色改为#f2e2e2，鼠标移出时，再将背景色改为白色。

##### 09. JS-案例-员工列表.html

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Tlias智能学习辅助系统</title>
    <style>
        /* 导航栏样式 */
        .navbar {
            background-color: #b5b3b3; /* 灰色背景 */
            
            display: flex; /* flex弹性布局 */
            justify-content: space-between; /* 左右对齐 */

            padding: 10px; /* 内边距 */
            align-items: center; /* 垂直居中 */
        }
        .navbar h1 {
            margin: 0; /* 移除默认的上下外边距 */
            font-weight: bold; /* 加粗 */
            color: white;
            /* 设置字体为楷体 */
            font-family: "楷体";
        }
        .navbar a {
            color: white; /* 链接颜色为白色 */
            text-decoration: none; /* 移除下划线 */
        }

        /* 搜索表单样式 */
        .search-form {
            display: flex;
            flex-wrap: nowrap;
            align-items: center;
            gap: 10px; /* 控件之间的间距 */
            margin: 20px 0;
        }
        .search-form input[type="text"], .search-form select {
            padding: 5px; /* 输入框内边距 */
            width: 260px; /* 宽度 */
        }
        .search-form button {
            padding: 5px 15px; /* 按钮内边距 */
        }

        /* 表格样式 */
        table {
            width: 100%;
            border-collapse: collapse;
        }
        th, td {
            border: 1px solid #ddd; /* 边框 */
            padding: 8px; /* 单元格内边距 */
            text-align: center; /* 左对齐 */
        }
        th {
            background-color: #f2f2f2;
            font-weight: bold;
        }
        .avatar {
            width: 30px;
            height: 30px;
        }

        /* 页脚样式 */
        .footer {
            background-color: #b5b3b3; /* 灰色背景 */
            color: white; /* 白色文字 */
            text-align: center; /* 居中文本 */
            padding: 10px 0; /* 上下内边距 */
            margin-top: 30px;
        }

        #container {
            width: 80%; /* 宽度为80% */
            margin: 0 auto; /* 水平居中 */
        }
    </style>
</head>
<body>
    <div id="container">
        <!-- 顶部导航栏 -->
        <div class="navbar">
            <h1>Tlias智能学习辅助系统</h1>
            <a href="#">退出登录</a>
        </div>

        <!-- 搜索表单区域 -->
        <form class="search-form" action="/search" method="post">
            <label for="name">姓名：</label>
            <input type="text" id="name" name="name" placeholder="请输入姓名">

            <label for="gender">性别：</label>
            <select id="gender" name="gender">
                <option value=""></option>
                <option value="1">男</option>
                <option value="2">女</option>
            </select>

            <label for="position">职位：</label>
            <select id="position" name="position">
                <option value=""></option>
                <option value="1">班主任</option>
                <option value="2">讲师</option>
                <option value="3">学工主管</option>
                <option value="4">教研主管</option>
                <option value="5">咨询师</option>
            </select>

            <button type="submit">查询</button>
            <button type="reset">清空</button>
        </form>

        <!-- 表格展示区 -->
        <table>
            <!-- 表头 -->
            <thead>
                <tr>
                    <th>姓名</th>
                    <th>性别</th>
                    <th>头像</th>
                    <th>职位</th>
                    <th>入职日期</th>
                    <th>最后操作时间</th>
                    <th>操作</th>
                </tr>
            </thead>

            <!-- 表格主体内容 -->
            <tbody>
                <tr>
                    <td>令狐冲</td>
                    <td>男</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="令狐冲"></td>
                    <td>讲师</td>
                    <td>2021-06-15</td>
                    <td>2024-09-16 15:30</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>任盈盈</td>
                    <td>女</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="任盈盈"></td>
                    <td>咨询师</td>
                    <td>2021-07-20</td>
                    <td>2024-09-17 09:00</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>向问天</td>
                    <td>男</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>班主任</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>任我行</td>
                    <td>男</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>教研主管</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>田伯光</td>
                    <td>男</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="令狐冲"></td>
                    <td>班主任</td>
                    <td>2021-06-15</td>
                    <td>2024-09-16 15:30</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>不戒</td>
                    <td>女</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="任盈盈"></td>
                    <td>班主任</td>
                    <td>2021-07-20</td>
                    <td>2024-09-17 09:00</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>左冷禅</td>
                    <td>男</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>班主任</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>定逸</td>
                    <td>女</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>班主任</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>东方兄弟</td>
                    <td>男</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>讲师</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
                <tr>
                    <td>金庸</td>
                    <td>男</td>
                    <td><img class="avatar" src="https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg" alt="向问天"></td>
                    <td>咨询师</td>
                    <td>2021-05-01</td>
                    <td>2024-09-15 17:45</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
            </tbody>
        </table>

        <!-- 页脚版权区域 -->
        <footer class="footer">
            <p>江苏传智播客教育科技股份有限公司</p>
            <p>版权所有 Copyright 2006-2024 All Rights Reserved</p>
        </footer>
    </div>

    <script>
        //通过JS为上述的表格中数据行添加事件监听, 实现鼠标进入后, 背景色#f2e2e2; 鼠标离开后, 背景色需要设置为#fff; (JS新版本的语法)
        // 1. 获取所有的tr标签
        let trs = document.querySelectorAll('tr');

        // 2. 为每一个tr标签添加事件监听
        for(let i = 0; i < trs.length; i++){
            trs[i].addEventListener('mouseenter', function(){ // mouseenter 鼠标进入
                trs[i].style.backgroundColor = '#f2e2e2';
            });
            
            trs[i].addEventListener('mouseleave', function(){ // mouseleave 鼠标离开
                trs[i].style.backgroundColor = '#fff';
            })
        }
    </script>
</body>
</html>
```

##### 常见事件
<figure><img src="/AiJavaWeb/imgs/jwai02-16.png"><figcaption>图16 常见事件</figcaption></figure>

##### 10. JS-常见事件.html

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JS-事件-常见事件</title>
</head>

<body>
    <h1>JS-事件-常见事件</h1>
    <hr>
    <form action="" style="text-align: center;">
        <input type="text" name="username" id="username">
        <input type="text" name="age" id="age">
        <input id="b1" type="submit" value="提交">
        <input id="b2" type="button" value="单击事件">
    </form>

    <br><br><br>

    <table width="800px" border="1" cellspacing="0" align="center">
        <tr>
            <th>学号</th>
            <th>姓名</th>
            <th>分数</th>
            <th>评语</th>
        </tr>
        <tr align="center">
            <td>001</td>
            <td>张三</td>
            <td>90</td>
            <td>很优秀</td>
        </tr>
        <tr align="center" id="last">
            <td>002</td>
            <td>李四</td>
            <td>92</td>
            <td>优秀</td>
        </tr>
    </table>

    
    <script>
        //click: 鼠标点击事件
        document.querySelector('#b2').addEventListener('click', () => {
            console.log("我被点击了...");
        })

        //mouseenter: 鼠标移入
        document.querySelector('#last').addEventListener('mouseenter', () => {
            console.log("鼠标移入了...");
        })

        //mouseleave: 鼠标移出
        document.querySelector('#last').addEventListener('mouseleave', () => {
            console.log("鼠标移出了...");
        })

        //keydown: 某个键盘的键被按下
        document.querySelector('#username').addEventListener('keydown', () => {
            console.log("键盘被按下了...");
        })

        //keyup: 某个键盘的键被抬起
        document.querySelector('#username').addEventListener('keyup', () => {
            console.log("键盘被抬起了...");
        })

        //blur: 失去焦点事件
        document.querySelector('#age').addEventListener('blur', () => {
            console.log("失去焦点...");
        })

        //focus: 元素获得焦点
        document.querySelector('#age').addEventListener('focus', () => {
            console.log("获得焦点...");
        })

        //input: 用户输入时触发
        document.querySelector('#age').addEventListener('input', () => {
            console.log("用户输入时触发...");
        })

        //submit: 提交表单事件
        document.querySelector('form').addEventListener('submit', () => {
            alert("表单被提交了...");
        })
    </script>
</body>
</html>
```



#### JS程序优化--模块化

<figure><img src="/AiJavaWeb/imgs/jwai02-17.png"><figcaption>图17 事件监听小结</figcaption></figure>

##### 11. JS-常见事件(优化).html

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JS-事件-常见事件</title>
</head>

<body>
    <h1>JS-事件-常见事件</h1>
    <hr>
    <form action="" style="text-align: center;">
        <input type="text" name="username" id="username">
        <input type="text" name="age" id="age">
        <input id="b1" type="submit" value="提交">
        <input id="b2" type="button" value="单击事件">
    </form>

    <br><br><br>

    <table width="800px" border="1" cellspacing="0" align="center">
        <tr>
            <th>学号</th>
            <th>姓名</th>
            <th>分数</th>
            <th>评语</th>
        </tr>
        <tr align="center">
            <td>001</td>
            <td>张三</td>
            <td>90</td>
            <td>很优秀</td>
        </tr>
        <tr align="center" id="last">
            <td>002</td>
            <td>李四</td>
            <td>92</td>
            <td>优秀</td>
        </tr>
    </table>
    
    <!-- type="module" 模块化JS -->
    <script src="./js/eventDemo.js" type="module"></script>
</body>
</html>
```

##### js/eventDemo.js

```javascript
import { printLog } from "./utils.js";

//click: 鼠标点击事件
document.querySelector('#b2').addEventListener('click', () => {
    printLog("我被点击了...");
})

//mouseenter: 鼠标移入
document.querySelector('#last').addEventListener('mouseenter', () => {
    printLog("鼠标移入了...");
})

//mouseleave: 鼠标移出
document.querySelector('#last').addEventListener('mouseleave', () => {
    printLog("鼠标移出了...");
})

//keydown: 某个键盘的键被按下
document.querySelector('#username').addEventListener('keydown', () => {
    printLog("键盘被按下了...");
})

//keyup: 某个键盘的键被抬起
document.querySelector('#username').addEventListener('keyup', () => {
    printLog("键盘被抬起了...");
})

//blur: 失去焦点事件
document.querySelector('#age').addEventListener('blur', () => {
    printLog("失去焦点...");
})

//focus: 元素获得焦点
document.querySelector('#age').addEventListener('focus', () => {
    printLog("获得焦点...");
})

//input: 用户输入时触发
document.querySelector('#age').addEventListener('input', () => {
  printLog("用户输入时触发...");
})

//submit: 提交表单事件
document.querySelector('form').addEventListener('submit', () => {
    alert("表单被提交了...");
})
```

##### js/utils.js

```javascript
export function printLog(msg){
  console.log(msg);
}
```



### Vue3

##### 什么是Vue

* Vue是一款用于<mark>构建用户界面</mark>的渐进式的JavaScript框架。 （官方：https://cn.vuejs.org/）

* 框架：就是一套完整的项目解决方案，用于快速构建项目 。
* 优点：大大提升前端项目的开发效率 。
* 缺点：需要理解记忆框架的使用规则 。（参照官网）

<figure><img src="/AiJavaWeb/imgs/jwai02-18.png"><figcaption>图18 数据构建用户界面</figcaption></figure>

<figure><img src="/AiJavaWeb/imgs/jwai02-19.png"><figcaption>图19 渐进式与生态</figcaption></figure>





#### 2.1 Vue 快速入门

* 基于数据渲染出用户看到的页面
* 数据驱动视图



* 准备
  * 引入Vue模块（官方提供）
  * 创建Vue程序的应用实例，控制视图的元素
  * 准备元素(div)，被Vue控制
* 数据驱动视图
  * 准备数据
  * 通过插值表达式渲染页面

<figure><img src="/AiJavaWeb/imgs/jwai02-20.png"><figcaption>图20 Vue快速入门</figcaption></figure>

##### 12. Vue-快速入门.html

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vue-快速入门</title>
  <script type="module">
    import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';

    createApp({
      data() {
        return {
          message: 'Hello Vue 杜老师',
          count: 100
        }
      }
    }).mount('#app');
  </script>
</head>
<body>
  <h1>Vue-快速入门(杜老师)</h1>
  <hr>
  <div id="app">
    <h1>{{message}}</h1>
    <h1>计数：{{count}}</h1>
  </div>
</body>
</html>
```

<figure><img src="/AiJavaWeb/imgs/jwai02-21.png"><figcaption>图21 Vue入门小结</figcaption></figure>

#### 2.2 Vue 常用指令

指令：HTML标签上带有 v-前缀的特殊属性，不同的<mark>指令</mark>具有不同的含义，可以实现不同的<mark>功能</mark>。

| **指令**              | **作用**                                                     |
| --------------------- | ------------------------------------------------------------ |
| v-for                 | 列表渲染，遍历容器的元素或者对象的属性                       |
| v-bind                | 为HTML标签绑定属性值，如设置 href , css样式等                |
| v-if/v-else-if/v-else | 条件性的渲染某元素，判定为true时<mark>渲染</mark>,否则<mark>不渲染</mark> |
| v-show                | 根据条件展示某元素，区别在于切换的是<mark>display属性</mark>的值 |
| v-model               | 在表单元素上创建双向数据绑定                                 |
| v-on                  | 为HTML标签绑定事件                                           |

##### 案例：员工列表数据渲染展示

<figure><img src="/AiJavaWeb/imgs/jwai02-22.png"><figcaption>图22 案例：员工列表数据渲染展示</figcaption></figure>

##### ① v-for

* 作用：列表渲染，遍历容器的元素或者对象的属性
* 语法： ```<tr v-for="(item,index) in items" :key="item.id"> {{item}}</tr>```
* 参数说明：
  * items 为遍历的数组
  * item 为遍历出来的元素
  * index 为索引/下标，从0开始 ；可以省略，省略index语法： v-for="item in items
* key：
  * 作用：给元素添加的唯一标识，便于vue进行列表项的正确排序复用，提升渲染性能
  * 推荐使用id作为key（唯一），不推荐使用index作为key（会变化，不对应）
* 注意：<mark>遍历的数组，必须在data中定义； 要想让哪个标签循环展示多次，就在哪个标签上使用 v-for 指令。</mark>

<figure><img src="/AiJavaWeb/imgs/jwai02-23.png"><figcaption>图23 v-for小结</figcaption></figure>



##### ② v-bind

* 作用：动态为HTML标签绑定属性值，如设置href，src，style样式等ma。
* 语法：v-bind:属性名="属性值" ```<img v-bind:src="item.image" width="30px">```
* 简化：:属性名="属性值"   ```<img :src="item.image" width="30px">```
* 注意：<mark>动态的为标签的属性绑定值，不能使用插值表达式，得使用v-bind指令。且绑定的数据，必须在data中定义或有data中定义的数据演变来的。</mark>

<figure><img src="/AiJavaWeb/imgs/jwai02-24.png"><figcaption>图24 v-bind小结</figcaption></figure>



##### ③ v-if & v-show

* 作用：这两类指令，都是用来控制元素的显示与隐藏的
* v-if
  * 语法：v-if="表达式"，表达式值为 true，显示；false，隐藏
  * 原理：<mark>基于条件判断，来控制创建或移除元素节点（条件渲染）</mark>
  * 场景：要么显示，要么不显示，不频繁切换的场景
  * 其它：可以配合 v-else-if / v-else 进行链式调用条件判断
* v-show
  * 语法：v-show="表达式"，表达式值为 true，显示；false，隐藏
  * 原理：<mark>基于CSS样式display来控制显示与隐藏</mark>
  * 场景：频繁切换显示隐藏的场景
* 注意：<mark>v-else-if必须出现在v-if之后，可以出现多个； v-else 必须出现在v-if/v-else-if之后 。</mark>

<figure><img src="/AiJavaWeb/imgs/jwai02-25.png"><figcaption>图25 v-if和v-show的区别</figcaption></figure>

<figure><img src="/AiJavaWeb/imgs/jwai02-26.png"><figcaption>图26 v-if和v-show小结</figcaption></figure>

##### ④ v-model

##### 案例：员工列表数据渲染，获取用户输入的条件
搜索栏中当用户点击查询按钮时，需要获取到用户输入的表单数据，并输出出来。

<figure><img src="/AiJavaWeb/imgs/jwai02-27.png"><figcaption>图27 v-model和v-on的使用场合</figcaption></figure>



* 作用：在表单元素上使用，<mark>双向数据绑定</mark>。可以方便的 <mark>获取 或 设置 表单项数据</mark> 
* 语法：v-model="变量名"
* 注意：<mark>v-model 中绑定的变量，必须在data中定义。</mark>

<figure><img src="/AiJavaWeb/imgs/jwai02-28.png"><figcaption>图28 v-model的双向数据绑定</figcaption></figure>

##### Chrome浏览器插件

地址：https://chrome.zzzmh.cn/#/index 下载nhdogjmejiglipccpnnnanhbledajbpd.zip并解压nhdogjmejiglipccpnnnanhbledajbpd_7.7.7_chrome.zzzmh.cn.crx

右上角菜单 -- 扩展程序 -- 管理扩展程序，将解压的crx拖入

##### firefox浏览器插件

https://addons.mozilla.org/zh-CN/firefox/

豆包：firefox vue插件工具下载和安装



##### ⑤ v-on

* 作用：为html标签绑定事件（添加事件监听）
* 语法：
  * v-on:事件名="方法名"
  * 简写为  @事件名="…"

* 注意：<mark>methods函数中的this指向Vue实例，可以通过this获取到data中定义的数据。</mark>
* <mark>v-on绑定的方法名必须指向当前组件作用域内可访问的函数（选项式 API 中是methods内的函数，组合式 API 中是 setup 内声明的函数）。</mark>



<figure><img src="/AiJavaWeb/imgs/jwai02-29.png"><figcaption>图29 v-model,v-on小结</figcaption></figure>



##### 13. Vue-案例-员工列表(常用指令).html

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Tlias智能学习辅助系统</title>
    <style>
        /* 导航栏样式 */
        .navbar {
            background-color: #b5b3b3; /* 灰色背景 */
            
            display: flex; /* flex弹性布局 */
            justify-content: space-between; /* 左右对齐 */

            padding: 10px; /* 内边距 */
            align-items: center; /* 垂直居中 */
        }
        .navbar h1 {
            margin: 0; /* 移除默认的上下外边距 */
            font-weight: bold; /* 加粗 */
            color: white;
            /* 设置字体为楷体 */
            font-family: "楷体";
        }
        .navbar a {
            color: white; /* 链接颜色为白色 */
            text-decoration: none; /* 移除下划线 */
        }

        /* 搜索表单样式 */
        .search-form {
            display: flex;
            flex-wrap: nowrap;
            align-items: center;
            gap: 10px; /* 控件之间的间距 */
            margin: 20px 0;
        }
        .search-form input[type="text"], .search-form select {
            padding: 5px; /* 输入框内边距 */
            width: 260px; /* 宽度 */
        }
        .search-form button {
            padding: 5px 15px; /* 按钮内边距 */
        }

        /* 表格样式 */
        table {
            width: 100%;
            border-collapse: collapse;
        }
        th, td {
            border: 1px solid #ddd; /* 边框 */
            padding: 8px; /* 单元格内边距 */
            text-align: center; /* 左对齐 */
        }
        th {
            background-color: #f2f2f2;
            font-weight: bold;
        }
        .avatar {
            width: 30px;
            height: 30px;
        }

        /* 页脚样式 */
        .footer {
            background-color: #b5b3b3; /* 灰色背景 */
            color: white; /* 白色文字 */
            text-align: center; /* 居中文本 */
            padding: 10px 0; /* 上下内边距 */
            margin-top: 30px;
        }

        #container {
            width: 80%; /* 宽度为80% */
            margin: 0 auto; /* 水平居中 */
        }
    </style>
</head>
<body>
    <div id="container">
        <!-- 顶部导航栏 -->
        <div class="navbar">
            <h1>Tlias智能学习辅助系统(杜老师)</h1>
            <a href="#">退出登录</a>
        </div>
        测试用{{searchForm}}
        <!-- 搜索表单区域 -->
        <form class="search-form">
            <label for="name">姓名：</label>
            <input type="text" id="name" name="name" v-model="searchForm.name" placeholder="请输入姓名">

            <label for="gender">性别：</label>
            <select id="gender" name="gender" v-model="searchForm.gender">
                <option value=""></option>
                <option value="1">男</option>
                <option value="2">女</option>
            </select>

            <label for="position">职位：</label>
            <select id="position" name="position" v-model="searchForm.job">
                <option value=""></option>
                <option value="1">班主任</option>
                <option value="2">讲师</option>
                <option value="3">学工主管</option>
                <option value="4">教研主管</option>
                <option value="5">咨询师</option>
            </select>

            <button type="button" v-on:click="search">查询</button>
            <button type="button" @click="clear">清空</button>
        </form>


        <!-- 表格展示区 -->
        <table>
            <!-- 表头 -->
            <thead>
                <tr>
                    <th>序号</th>
                    <th>id</th>
                    <th>姓名</th>
                    <th>性别</th>
                    <th>头像</th>
                    <th>职位</th>
                    <th>入职日期</th>
                    <th>最后操作时间</th>
                    <th>操作</th>
                </tr>
            </thead>

            <!-- 表格主体内容 -->
            <tbody>
                <tr v-for="(e, index) in empList" :key="e.id">
                    <td>{{index + 1}}</td>
                    <td>{{e.id}}</td>
                    <td>{{e.name}}</td>
                    <td>{{e.gender == 1?'男' : '女'}}</td>

                    <!-- 插值表达式是不能出现在标签内部属性值上，需要v-bind: 绑定属性值 -->
                    <td><img class="avatar"  v-bind:src="e.image" :alt="e.name"></td>

                    <!-- v-if: 控制元素的显示与隐藏 渲染与否-->
                    <td>
                        <span v-if="e.job == 1">班主任</span>
                        <span v-else-if="e.job == 2">讲师</span>
                        <span v-else-if="e.job == 3">学工主管</span>
                        <span v-else-if="e.job == 4">教研主管</span>
                        <span v-else-if="e.job == 5">咨询师</span>
                        <span v-else>其他</span>
                    </td>

                    <!-- v-show: 控制元素的显示与隐藏 display: none; 决定隐藏还是显示 -->
                    <!-- <td>
                        <span v-show="e.job == 1">班主任</span>
                        <span v-show="e.job == 2">讲师</span>
                        <span v-show="e.job == 3">学工主管</span>
                        <span v-show="e.job == 4">教研主管</span>
                        <span v-show="e.job == 5">咨询师</span>
                    </td> -->

                    <td>{{e.entrydate}}</td>
                    <td>{{e.updatetime}}</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
            </tbody>
        </table>

        <!-- 页脚版权区域 -->
        <footer class="footer">
            <p>杜氏教育工作室</p>
            <p>版权所有 Copyright 2006-2024 All Rights Reserved</p>
        </footer>
    </div>
    

    <script type="module">
      import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'

      createApp({
        data() {
          return {
            searchForm: { //封装用户输入的查询条件
                name: '',
                gender: '',
                job: ''
            },
            empList: [
              { "id": 1,
                "name": "谢逊",
                "image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/4.jpg",
                "gender": 1,
                "job": "1",
                "entrydate": "2023-06-09",
                "updatetime": "2024-09-30T14:59:38"
              },
              {
                "id": 2,
                "name": "韦一笑",
                "image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg",
                "gender": 1,
                "job": "1",
                "entrydate": "2020-05-09",
                "updatetime": "2024-09-01T00:00:00"
              },
              {
                "id": 3,
                "name": "黛绮丝",
                "image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/2.jpg",
                "gender": 2,
                "job": "2",
                "entrydate": "2021-06-01",
                "updatetime": "2024-09-01T00:00:00"
              }
            ]
          }
        },
        //方法
        methods: {
            search(){
                //将搜索条件, 输出到控制台
                console.log(this.searchForm);
            },
            clear(){
                //清空表单项数据
                this.searchForm = {name:'', gender:'', job:''}
            }
        },
      }).mount('#container')
    </script>

</body>
</html>
```



#### 2.3 Ajax

##### ① Ajax入门

##### 什么是Ajax

* 介绍：Asynchronous JavaScript And XML，<mark>异步</mark>的JavaScript和XML。
* 作用：
  * 数据交换：通过Ajax可以给服务器发送请求，并获取服务器响应的数据。
  * 异步交互：可以在<mark>不重新加载整个页面</mark>的情况下，与服务器交换数据并<mark>更新部分网页</mark>的技术，如：搜索联想、用户名是否可用的校验等等。
* XML：（英语：Extensible Markup Language）可扩展标记语言，本质是一种数据格式，可以用来存储复杂的数据结构。

<figure><img src="/AiJavaWeb/imgs/jwai02-30.png"><figcaption>图30 ajax</figcaption></figure>

##### 同步与异步

<figure><img src="/AiJavaWeb/imgs/jwai02-31.png"><figcaption>图31 同步与异步</figcaption></figure>

##### Axios

* 介绍：Axios 对原生的Ajax进行了封装，简化书写，快速开发。
* 官网：https://www.axios-http.cn/
* 步骤：
  * 引入Axios的js文件（参照官网）
  * 使用Axios发送请求，并获取响应结果

```html
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
```

<figure><img src="/AiJavaWeb/imgs/jwai02-32.png"><figcaption>图32 axios</figcaption></figure>

##### 14. Axios-入门.html

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ajax-入门s</title>
</head>
<body>
    <h1>Axios-入门(杜老师)</h1>
    <hr>
    <p>打开控制台查看请求结果</p>
    <input type="button" value="获取数据GET" id="btnGet">
    <input type="button" value="操作数据POST" id="btnPost">

    <script src="js/axios.js"></script>
    <script>
        //发送GET请求
        document.querySelector('#btnGet').addEventListener('click', () => {
            //axios发起异步请求
            axios({
                url: 'https://mock.apifox.cn/m1/3083103-0-default/emps/list',
                method: 'GET'
            }).then((result) => { //成功回调函数
                console.log(result.data);
            }).catch((err) => { //失败回调函数
                console.log(err);
            })
        })
        
        //发送POST请求
        document.querySelector('#btnPost').addEventListener('click', () => {
            //axios发起异步请求
            axios({
                url: 'https://mock.apifox.cn/m1/3083103-0-default/emps/update',
                method: 'POST',
                data: 'id=1' //POST请求方式 , 请求体
            }).then((result) => { //成功回调函数
                console.log(result.data);
            }).catch((err) => { //失败回调函数
                console.log(err);
            })
        })
    </script>
</body>
</html>
```



##### Axios-请求方式别名

* 为了方便起见，Axios已经为所有支持的请求方法提供了别名
* 格式：axios.请求方式(url [, data [, config]])



<figure><img src="/AiJavaWeb/imgs/jwai02-33.png"><figcaption>图33 axios-请求方式别名</figcaption></figure>

##### 15. Axios-请求方式别名.html

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ajax-Axios</title>
</head>
<body>
    <h1>Axios-请求方式别名(杜老师)</h1>
    <hr>
    <p>F12打开控制台查看请求结果</p>
    <input type="button" value="获取数据GET" id="btnGet">
    <input type="button" value="操作数据POST" id="btnPost">

    <script src="js/axios.js"></script>
    <script>
        //发送GET请求
        document.querySelector('#btnGet').addEventListener('click', () => {
            axios.get('https://mock.apifox.cn/m1/3083103-0-default/emps/list').then((result) => {
                console.log(result.data);
            });
            console.log('=============在异步结果出现之前显示=============');
        })
        
        //发送POST请求
        document.querySelector('#btnPost').addEventListener('click', () => {
            axios.post('https://mock.apifox.cn/m1/3083103-0-default/emps/update', 'id=1').then((result) => {
                console.log(result.data);
            });
            console.log('=============在异步结果出现之前显示=============');
        })
    </script>
</body>
</html>
```



<figure><img src="/AiJavaWeb/imgs/jwai02-34.png"><figcaption>图34 axios小结</figcaption></figure>

##### ② 案例

从服务器端动态获取数据渲染展示列表

服务端url地址： https://web-server.itheima.net/emps/list?name=xxx&gender=xxx&job=xxx

##### async & await

* 可以通过async、await可以让异步变为同步操作。async就是来声明一个异步方法，await是用来等待异步任务执行。
* 注意：<mark>await关键字只在async函数内有效，await关键字取代then函数，等待获取到请求成功的结果值</mark> 。

<figure><img src="/AiJavaWeb/imgs/jwai02-35.png"><figcaption>图35 async & await</figcaption></figure>

##### Vue生命周期

* 生命周期：指一个对象从创建到销毁的整个过程。
* 生命周期的八个阶段：每触发一个生命周期事件，会自动执行一个生命周期方法(钩子)。
* 生命周期的八个阶段：每触发一个生命周期事件，会自动执行一个生命周期方法(钩子)

| **状态**      | **阶段周期** |
| ------------- | ------------ |
| beforeCreate  | 创建前       |
| created       | 创建后       |
| beforeMount   | 载入前       |
| mounted       | 挂载完成     |
| beforeUpdate  | 数据更新前   |
| updated       | 数据更新后   |
| beforeUnmount | 组件销毁前   |
| unmounted     | 组件销毁后   |

<figure><img src="/AiJavaWeb/imgs/jwai02-36.png"><figcaption>图36 Vue生命周期</figcaption></figure>

<figure><img src="/AiJavaWeb/imgs/jwai02-37.png"><figcaption>图37 Vue生命周期</figcaption></figure>



##### 16. Vue-案例-员工列表(异步交互).html

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Tlias智能学习辅助系统</title>
    <style>
        /* 导航栏样式 */
        .navbar {
            background-color: #b5b3b3; /* 灰色背景 */
            
            display: flex; /* flex弹性布局 */
            justify-content: space-between; /* 左右对齐 */

            padding: 10px; /* 内边距 */
            align-items: center; /* 垂直居中 */
        }
        .navbar h1 {
            margin: 0; /* 移除默认的上下外边距 */
            font-weight: bold; /* 加粗 */
            color: white;
            /* 设置字体为楷体 */
            font-family: "楷体";
        }
        .navbar a {
            color: white; /* 链接颜色为白色 */
            text-decoration: none; /* 移除下划线 */
        }

        /* 搜索表单样式 */
        .search-form {
            display: flex;
            flex-wrap: nowrap;
            align-items: center;
            gap: 10px; /* 控件之间的间距 */
            margin: 20px 0;
        }
        .search-form input[type="text"], .search-form select {
            padding: 5px; /* 输入框内边距 */
            width: 260px; /* 宽度 */
        }
        .search-form button {
            padding: 5px 15px; /* 按钮内边距 */
        }

        /* 表格样式 */
        table {
            width: 100%;
            border-collapse: collapse;
        }
        th, td {
            border: 1px solid #ddd; /* 边框 */
            padding: 8px; /* 单元格内边距 */
            text-align: center; /* 左对齐 */
        }
        th {
            background-color: #f2f2f2;
            font-weight: bold;
        }
        .avatar {
            width: 30px;
            height: 30px;
        }

        /* 页脚样式 */
        .footer {
            background-color: #b5b3b3; /* 灰色背景 */
            color: white; /* 白色文字 */
            text-align: center; /* 居中文本 */
            padding: 10px 0; /* 上下内边距 */
            margin-top: 30px;
        }

        #container {
            width: 80%; /* 宽度为80% */
            margin: 0 auto; /* 水平居中 */
        }
    </style>
</head>
<body>
    <div id="container">
        <!-- 顶部导航栏 -->
        <div class="navbar">
            <h1>Tlias智能学习辅助系统(杜老师)</h1>

            <a href="#">退出登录</a>
        </div>
        
        <!-- 搜索表单区域 -->
        <form class="search-form">
            <label for="name">姓名：</label>
            <input type="text" id="name" name="name" v-model="searchForm.name" placeholder="请输入姓名">

            <label for="gender">性别：</label>
            <select id="gender" name="gender" v-model="searchForm.gender">
                <option value=""></option>
                <option value="1">男</option>
                <option value="2">女</option>
            </select>

            <label for="position">职位：</label>
            <select id="position" name="position" v-model="searchForm.job">
                <option value=""></option>
                <option value="1">班主任</option>
                <option value="2">讲师</option>
                <option value="3">学工主管</option>
                <option value="4">教研主管</option>
                <option value="5">咨询师</option>
            </select>

            <button type="button" v-on:click="search">查询</button>
            <button type="button" @click="clear">清空</button>
        </form>


        <!-- 表格展示区 -->
        <table>
            <!-- 表头 -->
            <thead>
                <tr>
                    <th>序号</th>
                    <th>姓名</th>
                    <th>性别</th>
                    <th>头像</th>
                    <th>职位</th>
                    <th>入职日期</th>
                    <th>最后操作时间</th>
                    <th>操作</th>
                </tr>
            </thead>

            <!-- 表格主体内容 -->
            <tbody>
                <tr v-for="(e, index) in empList" :key="e.id">
                    <td>{{index + 1}}</td>
                    <td>{{e.name}}</td>
                    <td>{{e.gender == 1?'男' : '女'}}</td>

                    <!-- 插值表达式是不能出现在标签内部 -->
                    <td><img class="avatar"  v-bind:src="e.image" :alt="e.name"></td>

                    <!-- v-if: 控制元素的显示与隐藏 -->
                    <td>
                        <span v-if="e.job == 1">班主任</span>
                        <span v-else-if="e.job == 2">讲师</span>
                        <span v-else-if="e.job == 3">学工主管</span>
                        <span v-else-if="e.job == 4">教研主管</span>
                        <span v-else-if="e.job == 5">咨询师</span>
                        <span v-else>其他</span>
                    </td>

                    <!-- v-show: 控制元素的显示与隐藏 -->
                    <!-- <td>
                        <span v-show="e.job == 1">班主任</span>
                        <span v-show="e.job == 2">讲师</span>
                        <span v-show="e.job == 3">学工主管</span>
                        <span v-show="e.job == 4">教研主管</span>
                        <span v-show="e.job == 5">咨询师</span>
                    </td> -->

                    <td>{{e.entrydate}}</td>
                    <td>{{e.updatetime}}</td>
                    <td class="action-buttons">
                        <button type="button">编辑</button>
                        <button type="button">删除</button>
                    </td>
                </tr>
            </tbody>
        </table>

        <!-- 页脚版权区域 -->
        <footer class="footer">
            <p>杜老师工作室</p>
            <p>版权所有 Copyright 2006-2024 All Rights Reserved</p>
        </footer>
    </div>
    
    <script src="js/axios.js"></script>
    <script type="module">
      import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'

      createApp({
        data() {
          return {
            searchForm: { //封装用户输入的查询条件
                name: '',
                gender: '',
                job: ''
            },
            empList: []
          }
        },
        //方法
        methods: {
            async search(){
                // 发送ajax请求，获取数据
                // axios.get(`https://web-server.itheima.net/emps/list?name=${this.searchForm.name}&gender=${this.searchForm.gender}&job=${this.searchForm.job}`).then((result) => {
                //     this.empList = result.data.data;
                // })
                // console.log('===========================');

                let result = await axios.get(`https://web-server.itheima.net/emps/list?name=${this.searchForm.name}&gender=${this.searchForm.gender}&job=${this.searchForm.job}`);
                this.empList = result.data.data;
            },
            clear(){
                //清空表单项数据
                this.searchForm = {name:'', gender:'', job:''}
                this.search()
            }
        },
        //钩子函数
        mounted(){
            //页面加载完成之后，发送ajax请求，获取数据
            this.search()
        }
      }).mount('#container')
    </script>

</body>
</html>
```

<figure><img src="/AiJavaWeb/imgs/jwai02-38.png"><figcaption>图38 Vue生命周期小结</figcaption></figure>

##### index.html

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>day02 JS+Vue+Ajax</title>
</head>
<body>
  <h1>ch2 JS+Vue+Ajax(杜老师)</h1>
  <hr>
  <p><a href="01. JS-引入方式.html" target="_self">01. JS-引入方式</a></p>
  <p><a href="02. JS-基础语法.html" target="_self">02. JS-基础语法</a></p>  
  <p><a href="03. JS-数据类型.html" target="_self">03. JS-数据类型</a></p> 
  <p><a href="04. JS-函数.html" target="_self">04. JS-函数</a></p>
  <p><a href="05. JS-自定义对象.html" target="_self">05. JS-自定义对象</a></p>
  <p><a href="06. JS-DOM.html" target="_self">06. JS-DOM</a></p>
  <p><a href="07. JS-案例-员工列表.html" target="_self">07. JS-案例-员工列表</a></p>
  <p><a href="08. JS-事件监听.html" target="_self">08. JS-事件监听</a></p>
  <p><a href="09. JS-案例-员工列表.html" target="_self">09. JS案例-员工列表</a></p>
  <p><a href="10. JS-常见事件.html" target="_self">10. 常见事件</a></p>
  <p><a href="11. JS-常见事件(优化).html" target="_self">11. 常见事件(优化)</a></p>
  <p><a href="12. Vue-快速入门.html" target="_self">12. Vue-快速入门</a></p> 
  <p><a href="13. Vue-案例-员工列表(常用指令).html" target="_self">13. Vue-案例-员工列表</a></p>
  <p><a href="14. Axios-入门.html" target="_self">14. Axios-入门</a></p>
  <p><a href="15. Axios-请求方式别名.html" target="_self">15. Axios-请求方式别名</a></p>
  <p><a href="16. Vue-案例-员工列表(异步交互).html" target="_self">16. Vue-案例-员工列表(异步交互)</a></p>
  <hr>
  <p><a href="/24ssm.html" target="_self">返回课程首页</a></p>
</body>
</html>
```



①②③④⑤⑥⑦⑧⑨⑩