用JS发请求和收响应,这就是AJAX的全部内容。

浏览器提供了一个XMLHttpRequest构造函数
image.png

准备一个server.js

server.js

安装node-dev

  1. yarn global add node-dev

使用node-dev
(好处:会自动重启)

  1. node-dev server.js 8888

添加index.html/main.js路由

  1. if(path === '/index.html'){
  2. response.statusCode = 200
  3. response.setHeader('Content-Type', 'text/html;charset=utf-8')
  4. response.write(`
  5. <!DOCTYPE html>
  6. <html>
  7. <head>
  8. <title>ajax</title>
  9. </head>
  10. <body>AJAX demo
  11. <script src="/main.js"></script>
  12. </body>
  13. </html>
  14. `)
  15. response.end()
  16. }else if(path === '/main.js'){
  17. response.statusCode = 200
  18. response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
  19. response.write(`
  20. console.log("我是JS")
  21. `)
  22. response.end()
  23. }else{
  24. response.statusCode = 404
  25. response.setHeader('Content-Type', 'text/html;charset=utf-8')
  26. response.write(`你输入的路径不存在对应的内容`)
  27. response.end()
  28. }

改成读取文件

  1. // 略
  2. response.setHeader('Content-Type', 'text/html;charset=utf-8')
  3. const string = fs.readFileSync('public/index.html')
  4. response.write(string)
  5. // 略
  6. response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
  7. const string = fs.readFileSync('public/main.js')
  8. response.write(string)
  9. // 略

挑战1:加载CSS

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>ajax</title>
  5. <link rel="stylesheet" href="style.css">
  6. </head>
  7. <body>
  8. <h1>AJAX demo 2</h1>
  9. <script src="/main.js"></script>
  10. </body>
  11. </html>
  1. if(path === '/style.css'){
  2. response.statusCode = 200
  3. response.setHeader('Content-Type', 'text/css;charset=utf-8')
  4. const string = fs.readFileSync('public/style.css')
  5. response.write(string)
  6. response.end()
  7. }

用ajax实现

  1. // 1. 创建HttpRequest()对象
  2. const request = new XMLHttpRequest()
  3. // 2. 调用对象的open方法,只传2个参数
  4. request.open('GET', '/style.css')
  5. // 3. 监听onload和onerror事件
  6. request.onload = ()=>{
  7. console.log(request.response)
  8. // 创建style节点
  9. const style = document.createElement("style")
  10. // 填写返回的内容
  11. style.innerHTML = request.response
  12. // 插到head里
  13. document.head.appendChild(style)
  14. }
  15. request.onerror = () =>{
  16. console.log("失败了")
  17. }
  18. // 4. 调用send方法,发送请求
  19. request.send()

挑战2: 加载JS

  1. const request = new XMLHttpRequest()
  2. request.open('GET', '/2.js')
  3. request.onload = ()=>{
  4. console.log(request.response)
  5. const script = document.createElement('script')
  6. script.innerHTML = request.response
  7. document.body.appendChild(script)
  8. }
  9. request.onerror = ()=>{}
  10. request.send()

挑战3: 加载HTML

  1. const request = new XMLHttpRequest()
  2. request.open('GET', '/3.html')
  3. request.onload = ()=>{
  4. console.log(request.response)
  5. const div = document.createElement('div')
  6. div.innerHTML = request.response
  7. document.body.appendChild(div)
  8. }
  9. request.onerror = ()=>{}
  10. request.send()

onreadystatechange

onerror没有很好的匹配ajax,因为先发明
改用onreadystatechange

XMLHttpRequest.readyState

image.png

XMLHttpRequest.status

响应分为五类:信息响应(100199),成功响应(200299),重定向(300399),客户端错误(400499)和服务器错误 (500599)。

  1. const request = new XMLHttpRequest()
  2. request.open('GET', '3.htm') // readyState === 1
  3. request.onreadystatechange = ()=>{
  4. if(request.readyState === 4) {
  5. // 4表示done,但不知道成功还是失败
  6. if (request.status >= 200 && request.status < 300) {
  7. const div = document.createElement('div')
  8. div.innerHTML = request.response
  9. document.body.appendChild(div)
  10. } else{
  11. alert("html加载失败")
  12. }
  13. }
  14. }
  15. request.send() // readyState === 2

挑战4:加载XML

XML (Extensible Markup Language) 可扩展标记语言

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <message>
  3. <warning>
  4. Hello World
  5. </warning>
  6. </message>

responseXML返回dom

  1. const request = new XMLHttpRequest()
  2. request.open('GET', '/4.xml')
  3. request.onreadystatechange = ()=>{
  4. if(request.readyState === 4) {
  5. if (request.status >= 200 && request.status < 300) {
  6. // console.log(request.responseXML) // 返回的是一个DOM
  7. const dom = request.responseXML
  8. const text = dom.getElementsByTagName('warning')[0].textContent.trim()
  9. console.log(text)
  10. } else{
  11. alert("xml加载失败")
  12. }
  13. }
  14. }
  15. request.send()

挑战5:加载JSON

JavaScript Object Notation
JSON是一门标记语言,与HTML, XML, Markdown一样,用来展示数据
中文官网:http://www.json.org.cn/index.htm

JSON支持的类型:

  • string
  • number
  • bool
  • null
  • object
  • array
  1. /* server.js 添加路由 */
  2. if(path === '/5.json'){
  3. response.statusCode = 200
  4. response.setHeader('Content-Type', 'text/json;charset=utf-8') // 也可以用application/json
  5. const string = fs.readFileSync('public/5.json')
  6. response.write(string)
  7. response.end()
  8. }
  1. getJSON.onclick = () => {
  2. const request = new XMLHttpRequest()
  3. request.open('GET', '/5.json')
  4. request.onreadystatechange = ()=>{
  5. if(request.readyState === 4 && request.status === 200){
  6. console.log(request.response)
  7. const obj = JSON.parse(request.response)
  8. console.log(obj)
  9. sayHi.textContent = "Hello " + obj.name
  10. }
  11. }
  12. request.send()
  13. }

window.JSON 对象
JSON.parse() 解析JSON字符串
JSON.stringify() 转成JSON字符串

  1. JSON.parse('{"name":"rose"}')
  2. JSON.stringify({name:"rose", age:18})
  3. try{
  4. let myName = JSON.parse(`{'name':"rose"}`)
  5. }catch(error){
  6. console.log(error)
  7. }

综合:加载分页

默认加载page1

  1. if(path === '/index.html'){
  2. response.statusCode = 200
  3. response.setHeader('Content-Type', 'text/html;charset=utf-8')
  4. let string = fs.readFileSync('public/index.html').toString()
  5. const page1 = fs.readFileSync('db/page1.json')
  6. const array = JSON.parse(page1)
  7. const result = array.map(item => `<li>${item.id}</li>`).join('')
  8. string = string.replace(`{{page1}}`,`<ul id="multiPages">${result}</ul>`)
  9. response.write(string)
  10. response.end()
  11. }

ajax请求page2

  1. let n = 1
  2. getPage.onclick = ()=>{
  3. const request = new XMLHttpRequest()
  4. request.open('GET', `/page${n+1}.json`) // 注意,第二个参数是server.js里的路由path
  5. request.onreadystatechange = ()=>{
  6. if(request.readyState === 4 && request.status === 200) {
  7. const array = JSON.parse(request.response)
  8. array.forEach(item => {
  9. const li = document.createElement('li')
  10. li.textContent = item.id
  11. multiPages.appendChild(li)
  12. })
  13. n+=1
  14. }
  15. }
  16. request.send()
  17. }