## 3. 交互式web应用前端开发技术
### 3.1 前端开发技术趋势介绍 (了解)
#### 3.1.1 前端技术栈的演进
- **早期阶段:** HTML、CSS 和 JavaScript 是构建网页的基本组成部分。
- **Web 2.0时代:** 出现了更多的动态网页技术和框架,如 jQuery 和 Prototype。
- **现代前端:** 进入了高度模块化和组件化的开发模式,出现了许多前端框架和库。
- **前端框架:** Angular、React、Vue.js 等。
- **任务运行器与打包工具:** gulp、webpack、parcel 等。
- **构建工具:** babel、eslint 等。
#### 3.1.2 前端框架和库的最新趋势
- **SPA (Single Page Application):** 单页面应用程序成为主流,它通过在不重新加载整个页面的情况下更新网页来提高用户体验。
- **组件化:** 将界面分解成可复用的组件,有助于提高开发效率和代码复用。
- **状态管理:** 如 Redux、Vuex 提供全局状态管理方案,帮助管理应用状态,特别是在大型应用中。
- **服务端渲染 (SSR):** 改善首屏加载速度,有利于SEO优化,因为搜索引擎爬虫更容易解析渲染在服务器端的页面。
- **前端自动化与持续集成:** 使用 CI/CD 工具提高开发效率,自动化测试和部署流程。
### 3.2 响应式设计与Bootstrap
#### 3.2.1 响应式设计的基本概念 (了解)
- **定义:** 响应式设计是一种使网站在所有设备和屏幕尺寸上都能良好显示的方法。
- **原理:** 使用流式布局、百分比单位、媒体查询等技术实现布局的自适应。
- **优势:** 提升用户体验、简化网站维护、提高搜索引擎排名。
#### 3.2.2 Bootstrap框架的使用 (了解)
Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架。Bootstrap 是基于 HTML、CSS、JAVASCRIPT 的。
参考[Bootstrap 教程](https://www.runoob.com/bootstrap/bootstrap-intro.html)
### 3.3 异步编程与AJAX
参考[ajax(PPT)](./resources/Ajax-heima.pptx)
#### 3.3.1 异步编程
在JavaScript中,异步编程是一个重要的概念,它允许程序在等待某些操作(如网络请求)完成的同时继续执行其他任务。回调函数是实现异步编程的一种早期方式,在现代JavaScript中仍然非常常见,尤其是在一些旧的库或API中。
##### 3.3.1.1 回调函数
回调函数是一种函数,作为参数传递给另一个函数,并且在这个函数内部被调用。这种方式常用于处理异步操作的结果。当一个异步操作完成时,通常会调用回调函数,并将结果或者错误作为参数传递给这个回调函数。
**示例**
下面是一个简单的使用回调函数进行异步操作的例子:
```javascript
function doSomethingAsync(callback) {
setTimeout(() => {
const result = '这是结果';
callback(result); // 在异步操作完成后调用回调函数
}, 1000);
}
// 使用回调函数
doSomethingAsync((result) => {
console.log('得到结果: ' + result);
});
```
在这个例子中,`doSomethingAsync` 函数模拟了一个耗时1秒的异步操作。当这个操作完成时,它通过调用 `callback` 函数来通知外部世界,并将结果传递给这个回调函数。
**回调地狱**
随着应用程序变得越来越复杂,回调函数可以导致所谓的“回调地狱”(Callback Hell),即嵌套的回调函数层次过深,使得代码难以阅读和维护。例如:
```javascript
doSomethingAsync((result1) => {
doAnotherThingAsync(result1, (result2) => {
doThirdThingAsync(result2, (result3) => {
console.log('所有操作完成');
});
});
});
```
为了解决这个问题,JavaScript 社区引入了 `Promise` 和 `async/await`,这些特性可以帮助我们以更简洁的方式编写异步代码。
##### 3.3.1.2 Promise对象
[Promise 10分钟,理论+实操](https://www.bilibili.com/video/BV1yu4y1H7ET/?spm_id_from=333.337.search-card.all.click&vd_source=fb252f6c305362a2870fb7388465df99)
[最好理解的Promise教程](https://www.bilibili.com/video/BV1454y1R7vj?p=1)
[异步编程: 一次性搞懂 Promise, async, await (#js #javascript)](https://www.bilibili.com/video/BV1WP4y187Tu/?spm_id_from=333.337.search-card.all.click&vd_source=fb252f6c305362a2870fb7388465df99)
`Promise` 是 JavaScript 中一种用于处理异步操作的模式,它旨在简化异步编程并解决回调地狱的问题。`Promise` 提供了一种更加结构化的处理异步操作的方法,使得代码更易读和维护。
一个 `Promise` 对象代表了一个最终可能会完成或失败的异步操作,并且它的完成(或失败)可能会发生在当前时刻,也可能是在未来的某个时刻。Promise 可以处于以下三种状态之一:
- **pending**(未定):初始状态,既不是成功也不是失败。
- **fulfilled**(已成功):意味着操作已完成,并且有一个值。
- **rejected**(已失败):意味着操作出现了错误,并且有一个原因(通常是错误对象)。
**创建 Promise**
创建一个 `Promise` 对象需要提供一个构造函数,该构造函数接受一个带有两个参数的执行器函数:`resolve` 和 `reject`。这两个函数用来改变 `Promise` 的状态:
- `resolve(value)`:当异步操作成功时调用,并传入结果值。
- `reject(reason)`:当异步操作失败时调用,并传入失败原因(通常是 `Error` 类型的一个实例)。
**示例**
这里是一个创建 `Promise` 并使用 `setTimeout` 模拟异步操作的例子:
```javascript
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('异步操作成功');
}, 1000);
});
promise.then(result => {
console.log(result); // 输出 "异步操作成功"
}).catch(error => {
console.error(error);
});
```
**链式调用**
`Promise` 的一个强大之处在于你可以链接多个 `.then()` 方法来指定一个操作序列。每个 `.then()` 方法返回一个新的 `Promise`,这允许你在链式调用中继续处理数据。
```javascript
new Promise(resolve => {
setTimeout(() => resolve(1), 1000);
}).then(result => {
console.log(result); // 输出 "1"
return result * 2;
}).then(newResult => {
console.log(newResult); // 输出 "2"
});
```
**错误处理**
如果在某个 `.then()` 方法中抛出了异常,或者之前的 `Promise` 被拒绝 (`rejected`),那么链式调用中的下一个 `.catch()` 方法就会捕获到这个错误。如果没有显式的 `.catch()` 处理错误,那么未处理的 `Promise` 拒绝会被作为全局错误处理。
```javascript
new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('出错了')), 1000);
}).then(result => {
console.log(result);
}).catch(error => {
console.error(error.message); // 输出 "出错了"
});
```
> `Promise` 是一种现代的异步编程模式,它可以让我们以更加结构化的方式编写代码。它不仅解决了回调地狱的问题,还提供了强大的错误处理机制。
##### 3.3.1.3 async异步函数/await表达式
`async/await` 是 JavaScript 中用于简化异步代码编写的一种语法糖。它使得异步代码看起来更像同步代码,提高了代码的可读性和可维护性。
**async 函数**
`async` 关键字用于声明一个函数为异步函数。一旦一个函数被声明为异步函数,它将总是返回一个 `Promise`。
```javascript
async function fetchUser() {
// 返回一个模拟的 Promise
return new Promise((resolve, reject) => {
setTimeout(() => resolve('User data'), 2000);
});
}
fetchUser().then(data => console.log(data)); // 输出: User data
```
**await 表达式**
`await` 关键字只能出现在 `async` 函数内部,它可以让 JavaScript 等待直到一个 `Promise` 完成(解决或拒绝)。`await` 后面跟的是一个 `Promise`,表达式的值就是 `Promise` 解决后的值。
```javascript
async function fetchData() {
try {
const response = await fetchUser();
console.log(response); // 输出: User data
} catch (error) {
console.error('Failed to fetch user:', error);
}
}
fetchData();
```
**异常处理**
如果 `Promise` 被拒绝(rejected),或者在 `await` 表达式之前或之后的代码中抛出了异常,可以通过在 `async` 函数内使用 `try...catch` 语句来捕获这些异常。
```javascript
async function example() {
try {
const result = await someAsyncFunctionThatMightFail();
console.log(result);
} catch (error) {
console.error('Caught an exception:', error);
}
}
```
**注意事项**
- `await` 只能出现在 `async` 函数内。
- 如果 `async` 函数内没有任何 `await` 表达式,那么它等同于一个普通函数,只是返回了一个已经解决的 `Promise`。
- 当 `async` 函数内的所有 `await` 操作都没有拒绝时,整个 `async` 函数会返回一个解决的 `Promise`;如果有任何 `await` 操作被拒绝或者抛出了异常,则会返回一个被拒绝的 `Promise`。
#### 3.3.2 XMLHttpRequest对象的使用 (了解)
[AJAX 简介](https://www.runoob.com/ajax/ajax-intro.html)
- **基本用法:** 创建对象、设置请求类型、发送请求、处理响应。
- **事件监听:** 监听 `onreadystatechange` 事件来获取服务器响应的状态。
- **请求方法:** `open` 方法设置请求类型和URL,`send` 方法发送请求。
```javascript
// 创建 XMLHttpRequest 对象
let xhr = new XMLHttpRequest();
// 设置请求类型和 URL
xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts/1', true);
// 设置响应类型
xhr.responseType = 'json';
// 设置请求完成后的回调函数
xhr.onload = function () {
if (this.status === 200) {
// 如果 HTTP 状态码为 200,则成功获取数据
var data = this.response; // 获取服务器响应的数据
console.log(data); // 在控制台打印数据
} else {
// 如果 HTTP 状态码不是 200,则打印错误信息
console.error('Error: ' + this.status);
}
};
// 设置请求错误时的回调函数
xhr.onerror = function () {
console.error('Request failed');
};
// 发送请求
xhr.send();
```
#### 3.3.3 Fetch API的使用 (掌握)
- **Fetch API:** 是一个现代替代 XMLHttpRequest 的 API,提供了更简洁的语法和基于 Promise 的接口。
- **基本语法:** `fetch(url)`返回一个 Promise 对象。
```javascript
const url = 'https://jsonplaceholder.typicode.com/posts/1';
// 使用 fetch 发送 GET 请求
fetch(url).then(response => {
// 检查响应状态
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// 解析 JSON 响应
return response.json();
}).then(data => {
// 处理解析后的 JSON 数据
console.log(data);
document.getElementById("title").innerHTML = data.title;
document.getElementById("content").innerHTML = data.body;
}).catch(error => {
// 处理任何发生的错误
console.error('There has been a problem with your fetch operation:', error);
});
```
代码解释:
>
> * 使用 fetch(url) 发送 GET 请求。
> * 使用 .then() 方法处理响应。第一个 .then() 接受响应对象,并检查其状态。
> * 如果响应状态码不在 200-299 范围内,则抛出一个错误。
> * 使用 response.json() 解析 JSON 响应,并返回解析后的数据。
> * 第二个 .then() 处理解析后的 JSON 数据。
> * 使用 .catch() 方法处理任何在前面的 Promise 链中抛出的错误。
-----
```javascript
// 发送 POST 请求并附加请求头
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST', // 或 'PUT'
headers: {
'Content-Type': 'application/json',
// 其他头部信息...
},
body: JSON.stringify({ title: 'axjax入门', body: 'abcdefghijklmn', userId: 1 }) // 转换为 JSON 字符串
}).then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}).then(data => {
console.log(data);
}).catch(error => {
console.error('There has been a problem with your fetch operation:', error);
});
```
代码解释:
> 在这个示例中,发送了一个包含 JSON 数据的 POST 请求,并在请求头中指定了 Content-Type 为 application/json。body 参数包含了要发送的数据,通过 JSON.stringify 方法将其转换为 JSON 字符串。
- **处理响应:** 使用`.then()`处理响应,如`.json()`或`.text()`。
- **错误处理:** 使用`.catch()`处理网络错误或其他异常。
#### 3.3.4 jQuery的AJAX API的使用 (掌握)
- **$.ajax():** jQuery 的 AJAX 方法,提供简单的语法糖。
- **$.get() 和 $.post():** 简化 GET 和 POST 请求的语法。
- **$.getJSON():** 专门用于获取 JSON 数据的快捷方法。
- **例子**
```javascript
let url = 'https://jsonplaceholder.typicode.com/posts/1';
$.get(url, function(data, textStatus, jqXHR) {
console.log('Data received:', data);
console.log('Text Status:', textStatus);
console.log('jqXHR:', jqXHR);
$("#title").html(data.title);
$("#content").html(data.body);
}).fail(function(jqXHR, textStatus, errorThrown) {
console.error('Request failed:', textStatus, errorThrown);
});
// 或者使用 $.ajax() 方法发送 GET 请求
$.ajax({
url: url,
type: 'GET',
success: function(data, textStatus, jqXHR) {
console.log('Data received:', data);
console.log('Text Status:', textStatus);
console.log('jqXHR:', jqXHR);
$("#title2").html(data.title);
$("#content2").html(data.body);
},
error: function(jqXHR, textStatus, errorThrown) {
console.error('Request failed:', textStatus, errorThrown);
}
});
```
**示例说明:**
**使用 `$.get()` 方法**:
- `$.get()` 是一个便捷的方法,用于发送 GET 请求。
- 第一个参数是请求的 URL。
- 第二个参数是一个回调函数,当请求成功时会被调用。
- 回调函数接受三个参数:`data`(服务器返回的数据)、`textStatus`(请求的状态字符串)和 `jqXHR`(`jQuery` 的 `XMLHttpRequest` 对象)。
- 使用 `.fail()` 方法来处理任何失败的情况。
**使用 `$.ajax()` 方法**:
- `$.ajax()` 方法是一个更通用的 AJAX 方法,可以用来发送各种类型的请求。
- 通过配置对象来指定请求的详细信息,例如 `url`(请求的 URL)、`type`(请求类型,如 `GET` 或 `POST`)等。
- `success` 和 `error` 属性分别用于处理成功和失败的情况。
- 这两个属性也是回调函数,它们接受与 `$.get()` 相同的参数。
**POST示例**
如果想发送 POST 请求或附加数据,可以使用 `$.ajax()` 方法并设置相应的参数。下面是一个发送 POST 请求并附加数据的示例:
```javascript
//发送 POST 请求
$.ajax({
url: 'https://jsonplaceholder.typicode.com/posts',
type: 'POST',
data: { title: 'axjax入门', body: 'abcdefghijklmn', userId: 1 }, // 附加数据
contentType: 'application/x-www-form-urlencoded', // 默认值,可以省略
success: function(data, textStatus, jqXHR) {
console.log('Post Data received:', data);
console.log('Post Text Status:', textStatus);
console.log('Post jqXHR:', jqXHR);
},
error: function(jqXHR, textStatus, errorThrown) {
console.error('Post failed:', textStatus, errorThrown);
}
});
```
在这个示例中:
- `data` 属性用于附加要发送的数据。
- `contentType` 属性指定发送数据的内容类型,默认是 `application/x-www-form-urlencoded`,对于 JSON 数据,你应该设置为 `application/json` 并使用 `JSON.stringify()` 方法来序列化数据。
### 3.4 XML简介(掌握)
#### 3.4.1 XML的基本概念
- **定义**: XML (eXtensible Markup Language) 是一种标记语言,用于描述数据的结构和意义。
- **用途**: XML被广泛用于Web服务、配置文件、数据交换等多种场景。
- **特点**:
- **自描述性**: XML文档自身描述了其结构。
- **平台无关性**: XML文档可以在任何平台上创建和解析。
- **可扩展性**: 可以定义新的标记和属性来描述数据。
#### 3.4.2 XML的数据结构
- **文档类型**: XML文档可以是无类型的或有类型的。
- **无类型文档**: 没有明确指定文档结构。
- **有类型文档**: 通过DTD或XML Schema定义文档结构。
- **元素**: XML文档的基本构建块,由开始标签、结束标签和内容组成。
- **属性**: 元素可以带有属性,用于提供额外的信息。
- **文本**: 元素的内容可以是纯文本或其他元素。
- **注释**: XML文档可以包含注释,注释不会被解析器处理。
- **处理指令**: 用于向解析器提供额外的指令。
#### 3.4.3 XML的语法
- **文档声明**: XML文档必须以文档声明开始。
```xml
```
- **元素**: 元素由开始标签和结束标签组成。
```xml
Example Book
John Doe
```
- **自闭合元素**: 如果元素没有内容,则可以自闭合。
```xml
```
- **属性**: 属性位于开始标签内。
```xml
```
- **文本**: 元素的内容可以是文本。
```xml
This is an example book.
```
- **注释**: XML文档可以包含注释。
```xml
```
#### 3.4.4 XML与Java对象的转换
- **序列化**: 将Java对象转换为XML文档的过程。
- **反序列化**: 将XML文档转换为Java对象的过程。
- **工具类**:
- **JAXB (Java Architecture for XML Binding)**: 用于将Java对象绑定到XML文档的标准API。
- **DOM (Document Object Model)**: 提供了表示XML文档的接口和方法。
- **SAX (Simple API for XML)**: 一种基于事件的解析器,用于处理大型XML文档。
- **StAX (Streaming API for XML)**: 类似于SAX,但提供了更好的性能和内存使用。
当然可以。以下是关于如何在JavaScript中处理XML的详细内容:
### 3.4.5 JavaScript中处理XML
在JavaScript中处理XML文档通常涉及以下几个方面:
#### 3.4.5.1. 解析XML文档
在JavaScript中解析XML文档通常有两种方法:使用DOM(Document Object Model)解析器和使用SAX(Simple API for XML)解析器。DOM解析器创建一个完整的文档树,而SAX解析器则逐个事件地处理文档流。
##### DOM解析器
DOM解析器可以将整个XML文档加载到内存中,并允许你像操作HTML文档一样操作XML文档。例如:
```javascript
function parseXmlWithDomParser(xmlString) {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
return xmlDoc;
}
const xmlString = "ToveJaniReminderDon't forget me this weekend!";
const xmlDoc = parseXmlWithDomParser(xmlString);
console.log(xmlDoc);
```
##### AJAX请求
如果你需要从服务器动态加载XML文档,可以使用AJAX技术。以下是一个使用`fetch` API的例子:
```javascript
async function loadXmlWithFetch(url) {
const response = await fetch(url);
const xmlString = await response.text();
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
return xmlDoc;
}
```
#### 3.4.5.2. 访问XML文档
一旦XML文档被解析成DOM树,就可以使用各种DOM方法来访问和操作它。
##### 选择元素
使用`getElementsByTagName`, `getElementsByClassName`, `getElementById`等方法来选择元素:
```javascript
const nodes = xmlDoc.getElementsByTagName("to");
nodes[0].textContent; // 输出 "Tove"
```
##### 修改元素
可以通过DOM节点的`textContent`, `innerHTML`, `appendChild`, `removeChild`等方法来修改文档:
```javascript
nodes[0].textContent = "New Tove";
```
#### 3.4.5.3. 创建和插入新元素
在DOM中创建新元素并将其插入到文档中:
```javascript
const newNode = xmlDoc.createElement("new");
const textNode = xmlDoc.createTextNode("New Text");
newNode.appendChild(textNode);
const root = xmlDoc.documentElement;
root.insertBefore(newNode, root.firstChild);
```
#### 3.4.5.4. 序列化XML文档
将DOM树转换回XML字符串或保存到磁盘/发送到服务器:
```javascript
const serializer = new XMLSerializer();
let xmlString = serializer.serializeToString(doc);
```
#### 3.4.5.5. 错误处理
在解析XML时,需要注意错误处理,确保在解析失败时能够妥善处理:
```javascript
try {
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
} catch (error) {
console.error("Error parsing XML:", error);
}
```
#### 3.4.6 XML的最佳实践
- **命名约定**: 使用有意义的元素和属性名称。
- **数据类型**: 正确使用XML的数据类型。
- **缩进和换行**: 使用适当的缩进和换行来提高可读性。
- **DTD和Schema**: 使用DTD或XML Schema来定义文档结构。
- **验证**: 在生产环境中使用验证器确保文档符合DTD或Schema。
- **安全性**: 对敏感数据进行加密或使用HTTPS传输。
- **版本控制**: 使用版本控制来跟踪XML文档的变化。
### 3.5 JSON简介
#### 3.5.1 JSON的基本概念
- **定义**: JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。
- **格式**: JSON 是基于JavaScript的一个子集,使用键值对的形式来组织数据。
- **用途**: 广泛用于Web应用的数据交换格式,特别是在Ajax应用中。
#### 3.5.2 JSON的数据结构
- **对象**: JSON中的对象是一个无序的“名值对”集合,使用大括号 `{}` 表示。
- **数组**: JSON中的数组是值的有序集合,使用方括号 `[]` 表示。
- **字符串**: JSON中的字符串使用双引号 `"` 包围。
- **数值**: JSON中的数值可以是整数或浮点数。
- **布尔值**: JSON中的布尔值可以是 `true` 或 `false`。
- **null**: JSON中的 `null` 表示没有值。
#### 3.5.3 JSON的语法
- **键值对**: 键和值之间使用冒号 `:` 分隔。
- **成员分隔**: 成员之间使用逗号 `,` 分隔。
- **示例**:
```json
{
"name": "John Doe",
"age": 30,
"isEmployed": true,
"address": {
"street": "123 Main St",
"city": "Anytown"
},
"phoneNumbers": [
{"type": "home", "number": "123-456-7890"},
{"type": "mobile", "number": "098-765-4321"}
]
}
```
#### 3.5.4 JSON与Java对象的转换
- **序列化**: 将Java对象转换为JSON字符串的过程。
- **反序列化**: 将JSON字符串转换为Java对象的过程。
- **工具类**:
- **Jackson**: 是一个流行的Java库,用于JSON的序列化和反序列化。
- **Gson**: Google提供的用于JSON处理的Java库。
### 3.5.5 JavaScript中处理Json
在JavaScript中,通常需要将JavaScript对象转换为JSON字符串,或者从JSON字符串解析出JavaScript对象。这个过程可以通过内置的`JSON.stringify()`和`JSON.parse()`方法来完成。
- **序列化** (`JSON.stringify()`): 这个方法用来将一个JavaScript值转化为JSON字符串。例如:
```javascript
var person = { name: "John", age: 30, city: "New York" };
var jsonStr = JSON.stringify(person);
```
- **反序列化** (`JSON.parse()`): 这个方法用来将JSON字符串解析成JavaScript值或对象。例如:
```javascript
var jsonStr = '{"name":"John","age":30,"city":"New York"}';
var person = JSON.parse(jsonStr);
```
#### 3.5.6 JSON的最佳实践
- **命名约定**: 使用有意义的键名。
- **数据类型**: 正确使用JSON的数据类型。
- **缩进和换行**: 使用适当的缩进和换行来提高可读性。
- **注释**: JSON本身不支持注释,但在开发阶段可以考虑使用工具添加注释。
- **安全**: 对敏感数据进行加密或使用HTTPS传输。
- **版本控制**: 使用版本控制来跟踪JSON数据的变化。
### 3.6 JavaScript框架介绍 (了解)
#### 3.6.1 Vue.js介绍
- **概述:** Vue.js 是一个用于构建用户界面的渐进式框架。
- **特点:** 易于上手、灵活、轻量级、双向数据绑定。
- **核心概念:** 组件、指令 (`v-model`, `v-if`, `v-for`)、插槽、生命周期钩子等。
- **生态系统:** Vuex (状态管理)、Vue Router (路由管理)。
#### 3.6.2 React.js介绍
- **概述:** React 是由 Facebook 开发的用于构建用户界面的 JavaScript 库。
- **特点:** 虚拟 DOM、组件化、单向数据流。
- **核心概念:** JSX、组件 (`class` 和 `function` 组件)、状态 (`state`) 和属性 (`props`)。
- **生态系统:** Redux (状态管理)、React Router (路由管理)。