Async JavaScript And XML
目录 § ⇧
-
1. AJAX原理 §
-
2. AJAX加载CSS §
-
3. AJAX加载JS §
-
4. AJAX加载HTML §
-
5. AJAX加载XML §
-
6. AJAX小结 §
-
7. JSON §
-
8. AJAX加载JSON §
-
9. window.JSON §
-
10. AJAX综合应用 §
-
11. 手写AJAX §
- 前后端交互
1. AJAX原理 § ⇧
AJAX是浏览器上的功能
- 用JS发请求和收响应
- 浏览器可以发请求,收响应
- 浏览器在
window
上加一个XMLHttpRequest
函数
typeof window.XMLHttpRequest
// function
- 用这个构造函数(类)可以构造出一个对象
- JS通过它实现发请求,收响应
准备服务器
- 使用 server.js 作为服务器
- 下载或复制代码即可用
node sever.js 8888
启动
- 使用
node-dev
工具 ,安装
yarn global add node-dev
# 或者用
npm install -g node-dev
- 用
node-dev
代替node
,实现自动重启服务器
- 但不能监听页面自动刷新
node-dev server.js 8888
- 添加
index.html / main.js
两个路由
- 路由就是
if..else
- 在
index.html
中加载路由读取的main.js
- 加载的文件中引用到的路径,必须和路由的
if..else
中的路径path
一致,server.js
才会加载
- 而
response.write(fs.readFileSync('src/xxx'))
中的是相对路径,和path
的不同
复习
- 在
server.js
中添加路由(条件),访问文件
- 添加
response.statusCode = 200
- 设置
Content-Type
为对应的类型response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
- 把文件读成字符串,再传入
response.write
- 结束,关闭
response.end()
const string = fs.readFileSync('src/index.html')
response.write(string)
文件实际上对于
node
服务器来说就是字符串,只不过把字符串写到文件里而已
【HTTP非全解】请求和响应 & Node.Js Server
2. AJAX加载CSS § ⇧
以前使用
<link rel="stylesheet" href="/style.css">
引入
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no,viewport-fit=cover">
<link rel="stylesheet" href="/style.css">
<title>AJAX demo</title>
</head>
<body>
<h1>AJAX demo</h1>
</body>
</html>
- 这里
--<link rel="stylesheet" href="/style.css">
中的/style.css"
是路由path
的请求路径
server.js
// ...
if (path === '/index.html') {
response.statusCode = 200
response.setHeader('Content-Type', 'text/html;charset=utf-8')
const string = fs.readFileSync('src/index.html')
response.write(string)
response.end()
}
// ...
style.css
body {
color: red;
background-color: #eaeaea;
}
使用 AJAX
加载 CSS
的四个步骤 ⇧
在
server.js
里写路由
// ...
if (path === '/index.html') {
response.statusCode = 200
response.setHeader('Content-Type', 'text/html;charset=utf-8')
const string = fs.readFileSync('src/index.html')
response.write(string)
response.end()
} else if (path === '/main.js') {
response.statusCode = 200
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
response.write(fs.readFileSync('src/main.js'))
response.end()
} else if (path === '/style.css') {
response.statusCode = 200
response.setHeader('Content-Type', 'text/css;charset=utf-8')
response.write(fs.readFileSync('src/style.css'))
response.end()
}
// ...
- 区别路由
path
的请求路径和fs.readFileSync('src/xxx')
的查找文件目录路径
index.html
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no,viewport-fit=cover">
<!-- <link rel="stylesheet" href="/style.css"> -->
<title>AJAX demo 2</title>
</head>
<body>
<h1>AJAX demo CSS</h1>
<p>
<button id="getCSS">请求CSS</button>
</p>
<script src="/main.js"> </script>
</body>
</html>
-
index.html
里写的所有路径(/style.css
和/main.js
),必须和路由的path
路径一致,才能生效
- 创建一个 button 测试
在
main.js
里写
getCSS.onclick = () => {
const request = new XMLHttpRequest()
request.open('GET', '/style.css');
request.onload = () => {
// console.log('成功了')
console.log('request.response')
console.log(request.response)
// 之后将响应的内容,用对应的标签包裹,插入html页面相应位置
}
request.onerror = () => {
console.log('失败了')
}
request.send()
}
- 创建
HttpRequest
对象 (全称是XMLHttpRequest
)
- 调用对象的
open
方法
- 监听对象的
onload
和onerror
事件
- 调用对象的
send
方法(发送请求)
- 获取资源用
request.open('GET', '/xxx');
,只用两个参数,mdn 中后面的参数不用XMLHttpRequest.open() MDN
而
request.response
就是响应得到的文件内容
- 要使这段内容生效,就在外包裹一层对应的标签
// 将响应的内容,用对应的标签包裹,插入html页面相应位置
const style = document.createElement('style') // 创建 style 标签
style.innerHTML = request.response // 填写 style 内容
document.head.appendChild(style) // 插入head标签里
触发
onerror
事件
request.onerror = () => {
console.log('失败了')
}
-
server.js
路径写错:你输入的路径不存在对应的内容
//...
else {
response.statusCode = 404
response.setHeader('Content-Type', 'text/html;charset=utf-8')
response.write(`你输入的路径不存在对应的内容`)
response.end()
}
//...
- 只会渲染路径错误时的路由,并不触发
onerror
事件
-
onerror
对AJAX的支持不好
在第3步中,AJAX一般改用
onreadystatechange
事件,不用onload
和onerror
- 用对象的
status
属性,即状态码来判断,响应是否成功
- 注意
onreadystatechange
全小写
getCSS.onclick = () => {
const request = new XMLHttpRequest()
request.open('GET', '/style.css');
request.onreadystatechange = () => {
// 监听对象的 readyState属性
// console.log(request.readyState) // 2 3 4
if (request.readyState === 4) {
// console.log('下载完成')
// 下载完成,但不知道下载成功还是失败
if (request.status >= 200 && request.status < 300) {
// 将响应的内容,用对应的标签包裹,插入html页面相应位置
const style = document.createElement('style') // 创建 style 标签
style.innerHTML = request.response // 填写 style 内容
document.head.appendChild(style) // 插入head标签里
} else {
console.log('加载CSS失败')
}
}
}
request.send()
}
- 在事件处理函数里操作 CSS 文件内容
-
XMLHttpRequest.onreadystatechange MDN
-
XMLHttpRequest.readyState相关状态,4 表示下载完成
3. AJAX加载JS § ⇧
以前使用
<script src="main.js"></script>
引入
使用 AJAX
加载 JS
的四个步骤 ⇧
server.js
// ...
else if (path === '/getJS.js') {
response.statusCode = 200
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
response.write(fs.readFileSync('src/getJS.js')) // 在目录中创建一个测试的getJS.js
response.end()
}
//...
index.html
<p>
<button id="getCSS">请求CSS</button>
<button id="getJS">请求JS</button>
</p>
- 创建
HttpRequest
对象 (全称是XMLHttpRequest
)
- 调用
open
方法
- 监听对象的
onreadystatechange
事件
- 调用对象的
send
方法(发送请求)
main.js
//...
// AJAX 加载 JS
getJS.onclick = () => {
const request = new XMLHttpRequest
request.open('GET', '/getJS.js')
request.onreadystatechange = () => {
if (request.readyState === 4 && request.status >= 200 && request.status < 300) {
// 创建script标签
const script = document.createElement('script')
// 填写 script内容
script.innerHTML = request.response
// 插到body里
document.body.appendChild(script)
}
}
request.send()
}
//...
- 在事件处理函数里操作 JS 文件内容
- 将响应的内容,用对应的标签包裹,插入html页面相应位置
- AJAX下载并执行响应的内容
4. AJAX加载HTML § ⇧
以前没有加载过 HTML
- 在目录
src/
下创建测试用indexOld.html
,不写全,只写个标签
<h2>AJAX demo 2</h2>
<div style="background-color: bisque;border: 1px solid orange;width:300px;height:300px;">动态内容</div>
配置路由
server.js
//...
else if (path === '/indexOld.html') {
response.statusCode = 200
response.setHeader('Content-Type', 'text/html;charset=utf-8')
response.write(fs.readFileSync('src/indexOld.html'))
response.end()
}
//...
index.html 加测试按钮
<p>
<button id="getCSS">请求CSS</button>
<button id="getJS">请求JS</button>
<button id="getHTML">请求HTML</button>
</p>
使用 AJAX
加载 HTML
的四个步骤 ⇧
- 创建
HttpRequest
对象
- 调用对象的
open
方法
- 监听对象的
onreadystatechange
事件
- 调用对象的
send
方法
//...
// AJAX 加载 HTML
getHTML.onclick = () => {
const request = new XMLHttpRequest
request.open('GET', '/indexOld.html')
request.onreadyStatechange = () => {
if (request.readyState === 4 && request.status >= 200 && request < 300) {
// 创建 div 标签
const div = document.createElement('div')
// 填写 div 内容
div.innerHTML = request.response
// 插到body里
document.body.appendChild(div)
}
}
request.send()
}
//...
- 在事件处理函数里操作
HTML
文件内容
- 动态展示
index.html
- 控制台
Network
查看请求 点Preview
预览请求的页面
- 点
Response
看源代码
- 把页面拆成不同的部分,在用户点击时,请求这个部分
- 可以请求一小块 HTML,而
iframe
是请求整个网页,更加臃肿
-
AJAX
可以做到轻量级的请求,任意 HTTP 支持的文件类型
5. AJAX加载XML § ⇧
使用 AJAX
加载 XML
的四个步骤 ⇧
server.js
//...
else if (path === '/getXML.xml') {
response.statusCode = 200
response.setHeader('Content-Type', 'text/xml;charset=utf-8')
response.write(fs.readFileSync('src/getXML.xml'))
response.end()
}
//...
index.html
<p>
<button id="getCSS">请求CSS</button>
<button id="getJS">请求JS</button>
<button id="getHTML">请求HTML</button>
<button id="getXML">请求XML</button>
</p>
getXML.xml
<?xml version="1.0" encoding="UTF-8"?>
<message>
<warning>
Hello World
</warning>
</message>
- 创建
HttpRequest
对象(全称是XMLHttpRequest
)
- 调用对象的
open
方法
- 监听对象的
onreadystatechange
事件
- 调用对象的
send
方法(发送请求)
main.js
// AJAX 加载 XML
getXML.onclick = () => {
const request = new XMLHttpRequest()
request.open('GET', '/getXML.xml')
request.onreadystatechange = () => {
if (request.readyState === 4 && request.status >= 200 && request.status < 300) {
// console.log(request.responseXML)
const dom = request.responseXML
const text = dom.getElementsByTagName('warning')[0].textContent.trim();
console.log(text)
console.log(request.responseXML)
}
}
request.send()
}
- 在事件处理函数里操作
responseXML
-
request.responseXML
是 DOM 对象
6. AJAX小结 § ⇧
HTTP 可以请求的类型 ⇧
- 可以请求
HTML
CSS
JS
...
- 设置正确的
Content-Type
- 响应的内容,用对应的标签包裹,插入html页面相应位置
- 知道怎么解析,就可以使用
解析方法 ⇧
- 得到 CSS 后生成
style
- 得到 JS 后生成
script
- 得到 HTML 使用
innerHTML
和DOM API
- 得到 XML 后使用
responseXML
和DOM API
- 不同类型的数据有不同的解析办法
7. JSON § ⇧
Java*Script **Object **N*otation
- JSON 是 轻量级的数据交换格式语言
- 和HTML CSS JS一样是门独立的语言
- 和HTML XML Markdown 是 标记语言,用来展示数据
-
中文官网
- 一页纸
- 铁轨图
支持的类型 ⇧
-
string
只支持双引号,不支持单引号、反引号和无引号
-
number
支持科学技术法
-
bool
true
和false
-
null
没有undefined
-
object
-
array
区别于 JS 的类型
- 不支持函数与变量(即不支持引用)
和JS语法的区别:
- JSON 的字符串必须用双引号。
- JSON 无法表示 undefined,只能表示 "undefined"
- JSON 无法表示函数
- JSON 的对象语法不能有引用
8. AJAX加载JSON § ⇧
server.js
else if (path === '/getJSON.json') {
response.statusCode = 200
response.setHeader('Content-Type', 'text/json;charset=utf-8') // 'application/json;charset=utf-8'也可
response.write(fs.readFileSync('src/getJSON.json'))
response.end()
}
getJSON.json
{
"name": "frank",
"gender": "male",
"age": 18,
"xxx": null
}
index.html
<p>
<button id="getCSS">请求CSS</button>
<button id="getJS">请求JS</button>
<button id="getHTML">请求HTML</button>
<button id="getXML">请求XML</button>
<button id="getJSON">请求JSON</button>
</p>
<h2>Hello <span id="myName"></span></h2>
使用 AJAX
加载 JSON
的四个步骤 ⇧
- 创建
HttpRequest
对象(全称是XMLHttpRequest
)
- 调用对象的
open
方法
- 监听对象的
onreadystatechange
事件
- 调用对象的
send
方法(发送请求)
main.js
// AJAX 加载 JSON
getJSON.onclick = () => {
const request = new XMLHttpRequest()
request.open('GET', '/getJSON.json')
request.onreadystatechange = () => {
if (request.readyState === 4 && request.status === 200) {
console.log(request.response)
const object = JSON.parse(request.response)
console.log(object)
myName.textContent = object.name
}
}
request.send()
}
- 在事件函数里使用
JSON.parse
-
JSON.parse
把符合 JSON 语法的字符串变成对应的对象或者是其他东西
9. window.JSON § ⇧
JSON.parse
⇧
- 解析字符串
- 将符合
JSON
语法的字符串转换成JS
对应类型的数据
-
JSON
字符串 -> JS 数据
- 转换成的不一定是对象,可以是 JSON 值类型的其他类型( typeof )
- 由于 JSON 只有六种类型,所以转成的数据也只有6种
- 如果不符合
JSON
语法,则直接抛出一个Error
对象
- 一般用
try...catch
捕获错误
let object
try{
object = JSON.parse(`{'name':'frank'}`)
}catch(error){
console.log('Error!')
console.log(error)
object = {"name":"no name"}
}
console.log(object)
JSON.stringify
序列化 ⇧
- 是
JSON.parse
的逆运算
- JS 数据 ->
JSON
字符串
- 由于 JS 的数据类型比 JSON 多,所以不一定成功
- 如果失败,则直接抛出一个
Error
对象
const obj = {"hi": "Ho", fn=(){}}
JSON.stringify(obj) // 不报错 直接忽略不合法的类型
10. AJAX综合应用:加载分页 § ⇧
加载列表 ⇧
- 用户打开页面,开到第一页数据
- 用户点击下一页,看到第二页数据
- 用户点击下一页,看到第三页数据
- 用户点击下一页,提示没有更多了
/db/page1.json page2.json page3.json
- 前后端不分离的渲染
index.html
<body>
<!-- ... -->
<h2>Hello <span id="myName"></span></h2>
<div>
{{page1}}
</div>
<!-- ... -->
</body>
server.js
if (path === '/index.html') {
response.statusCode = 200
response.setHeader('Content-Type', 'text/html;charset=utf-8')
let string = fs.readFileSync('src/index.html').toString() // 调用toString()前 是buffer
// AJAX分页
const page1 = fs.readFileSync('db/page1.json')
// li
const array = JSON.parse(page1) // [{ "id": 1 }, { "id": 2 }, { "id": 3 }, { "id": 4 }, { "id": 5 }, { "id": 6 }, { "id": 7 }, { "id": 8 }, { "id": 9 }, { "id": 10 }]
const result = array.map(item => {
return `<li>${item.id}</li>`
}).join('')
string = string.replace('{{page1}}', `<ul>${result}</ul>`)
response.write(string)
response.end()
}
- 从数据库中拿出,拼接字符串
main.js
let pageCount = 1
// AJAX 加载 分页
getPage.onclick = () => {
const request = new XMLHttpRequest()
request.open('GET', `/page${pageCount + 1}`)
request.onreadystatechange = () => {
if (request.readyState === 4 && request.status === 200) {
const array = JSON.parse(request.response)
array.forEach(item => {
const li = document.createElement('li')
li.textContent = item.id
xxx.appendChild(li)
});
// console.log(request.response)
const object = JSON.parse(request.response)
// console.log(object)
myName.textContent = object.name
pageCount += 1
}
}
request.send()
}
优化点 ⇧
- 在点击第三页的时候就禁用下一页按钮
main.js
//...
let page = [1, 2, 3]
let currentPage = page[0]
// AJAX 加载 分页
getPage.onclick = () => {
if (currentPage < 3) {
const request = new XMLHttpRequest()
request.open('GET', `/page${currentPage + 1}`)
request.onreadystatechange = () => {
if (request.readyState === 4 && request.status === 200) {
const array = JSON.parse(request.response)
array.forEach(item => {
const li = document.createElement('li')
li.textContent = item.id
xxx.appendChild(li)
});
// console.log(request.response)
const object = JSON.parse(request.response)
// console.log(object)
myName.textContent = object.name
currentPage += 1
}
}
request.send()
} else {
// console.log("Ban")
getPage.disabled = true
}
}
//...
11. 手写AJAX § ⇧
使用原生 JS 写出一个 AJAX 请求
mybutton.onclick = () => {
let request = new XMLHttpRequest()
request.open('GET','/xxx')
request.onreadystatechange = () => {
if(request.readystate === 4 && request.status = 200) {
let string = request.responseText
let string = window.JSON.parse(string)
}
}
request.send()
}
后台的server.js,处理请求
if(path === '/xxx') {
response.statusCode = 200
response.setHeader('Content-Type','text/json;charset=utf-8')
response.write(`{"status":"ok"}`)
response.end()
}
·未完待续·
参考链接
- 作者: Joel
- 文章链接:
-
版权声明
- 非自由转载-非商用-非衍生-保持署名