AJAX基础
1.前端与后端
前端:指的是一切用户看到的界面,都是属于前端的工作范围,比如浏览器中看到的页面,或是手机里面看到的那些APP...
后端:主要是指的与数据库进行交互,向前端开放接口,返回对应的数据
2.演示浏览器与服务器端的交互
1.我们将写好的页面上传到了服务器,供所有的人来访问
2.用户打开自己电脑中的浏览器,输入域名或IP地址,向服务器发送请求
3.服务器接收到这个请求,进行处理,将用户请求的页面的源代码响应给对应的浏览器
4.浏览器接收到这个响应数据(源代码,html+css+js)后,进行处理,最终将源代码呈现到我们的浏览器上,让我看到真正的页面
5.这就是浏览器与服务器端的一个基本交互过程
3.实现自身服务器功能的访问
1.将接收到的server.rar文件解压出来
2.在这个文件夹中的views文件夹中新建index.html,写页面基本布局和样式
3.然后双击启动.bat这个文件,表示启动服务器
4.在浏览器输入127.0.0.1:3001/index.html,之后回车,查看页面效果
4.网络相关概念介绍
-
服务器:就是指专门安装了某些服务功能性质的软件的机器,按功能来区分的话,
-
web服务器,提供页面访问的
-
数据库服务器,专门用来提供数据访问
-
邮件服务器,收发网络邮件
-
客户端:就是指享受提供服务的终端设置,在我们电脑上指的是浏览器
-
IP地址:IP地址是用于定位或标识网络中的终端设备的,终端设备比如:PC,手机,平板,智能家电...
-
127.0.0.1称为本机回环地址,只要是我们电脑安装了操作系统,就会有一个私有的IP:127.0.0.1
-
localhost:相当于 是我们本机的域,和127.0.0.1是对应的,是等价的
-
端口: 端口是用来区分电脑中的应用程序的,应用程序如:飞秋,内网通,数据库,淘宝旺旺...
-
域名:域名其实是和IP对应的,因为IP是四组阿拉伯数字组成 ,没有什么规律,不好记忆,因此人们就给这个IP起了个别名,就是这个域名,用这个域名来代替IP
-
www.baidu.com 119.75.213.51
-
www.taobao.com 103.43.210.219
-
www.mi.com 211.162.52.55
-
DNS服务器:专门用于解析域名和IP地址之间的映射关系。
-
端:指的终端或终端设备,比如电脑,手机,智能家电
5.HTTP协议
简单来说,HTTP协议就是一种端与端之间的通讯 协议.
HTTP协议规范了请求和响应的报文格式:
请求报文:
-
请求行 请求报文主要内容有:请求的方式(get/post),请求的目标地址,协议版本
-
请求头 是浏览器端发送给服务器端的关于客户端的一些额外数据,比如:发送过去的数据编码方式是什么,客户端的操作系统是什么,客户端用的是什么浏览器
-
请求体 是客户端浏览器发送给服务器的真正的数据值,比如说:用户名,密码,手机号,爱好 ,家庭地址啊...
响应报文:
-
状态行 报文内容主要包括: 状态码,状态描述,协议版本
-
响应头 是服务器端发送给客户端的有关服务器端的一些额外数据,比如:服务器端的软件版本,服务器端的操作系统,服务器端的时间,服务器告诉浏览器端如何解析响应回去的数据(Content-Type)
-
响应体 服务器端响应给浏览器端的真正的数据(比如可能是源代码,有可能是json格式的具体数据...)
6.异步
同步:同一时间只能做一件事,会阻塞主程序的执行
异步:同一时间可以做多件事情,可以通过异步对象来实现,不会阻塞主程序的执行
7.前后端数据交互的格式
1.字符串
2.二进制
JSON.parse():可以将字符串数组或字符串对象解析成真正的数组或对象
JSON.stringify():是将真正的数组或对象转换成对应的字符串
8.URL
专业名词叫统一资源定位符,其实就是网址或域名或IP地址等.
9.表单
如果想让将浏览器端的数据收集起来,此时就需要用到form表单.
form标签有两个非常重要的属性:
-
action:表示要提交的服务器地址,如果不写默认是提交给自己
-
method:表示提交的方式,如果不写默认是get
10.get请求的特点
-
get方式在url后面拼接参数,只能以文本的形式传递数据
-
传递的数据量小,4KB左右(不同浏览器会有差异)
-
安全性低,会将数据显示在地址栏
-
速度快,通常用于对安全性要求不高的请求
11.post请求的特点
1-post 方式 安全性比较高
2-传递数据量大,请求对数据长度没有要求
3-请求不会被缓存,也不会保留在浏览器历史记录中
用于:密码等安全性要求比较高的场合,提交的数据量比较大:发布文章,上传文件。
12.使用异步对象来发送请求
使用异步对象在http协议的基础上来发送请求
-
1.创建异步对象 var xhr = new XMLHttpRequest()
-
2.设置请求行 xhr.open()
-
3.设置请求头
-
4.设置请求体 xhr.send()
-
5.监视异步对象的状态 xhr.responseText来接收服务器响应回来的数据
13.案例
1.使用AJAX异步对象发送get请求
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>初识AJAX</title> <style> * { margin: 0; padding: 0; list-style: none; } .box { width: 300px; height: 300px; background-color: pink; text-align: center; line-height: 300px; font-size: 30px; } </style> </head> <body> <h2>开始学习AJAX技术了,真刺激,我喜欢.</h2> <div class="box">0</div> <input type="button" value="使用AJAX异步加载名字" id="btn"> <ul></ul> <script> // 查找元素 var btn = document.querySelector('#btn'); var box = document.querySelector('.box'); var ul = document.querySelector('ul'); // 设置一个定时器让盒子中的计时一直增加 var num = 0; setInterval(function(){ num++; box.innerHTML = num; },1000); // 给按钮绑定点击事件 btn.addEventListener('click', function(){ // 使用AJAX异步对象发送请求给服务端 // 1.1 创建一个异步实例对象 var xhr = new XMLHttpRequest(); // 1.2 设置请求行 三个参数: 请求方式get/post 请求目标服务器地址 是否异步(默认),ture(异步),false(同步) xhr.open('get', "http://127.0.0.1:3001/getData", true); // 通过getData接口请求服务器的数据 // 因为这个使用的是get方式请求服务器,可以省略不写,模块会自动生成 // 1.4 设置请求体 // 由于是get请求,请求体没有数据,所以写null xhr.send(null); // 1.5 监听异步对象状态 xhr.onreadystatechange = function(){ console.log(xhr.readyState); // 一次成功的请求和响应,至少包括两个方面 // 第一个,将请求发送过去,服务器端接收到响应并做了处理,状态码用200表示 // 第二个,接受到数据之后,必须保证全部的数据都接收到,而且都对接收到的数据进行完全的解析或处理 状态值为4 if(xhr.status==200 && xhr.readyState==4){ console.log(xhr.responseText); //异步对象的responseText来接收服务器端响应回来的数据 console.log(typeof xhr.responseText); //将字符串对象转换成数组或对象格式 var obj = JSON.parse(xhr.responseText); var data = obj.data; for(var i=0; i<data.length; i++){ // 创建一个元素 var li = document.createElement('li'); li.innerHTML = data[i].name; // 插入数据 ul.appendChild(li); } } } }) </script> </body> </html>
效果
2. 使用AJAX异步对象发送get请求
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>注册用户名</title> </head> <body> <form action="/submit" method="get"> 用户名: <input type="text" name="userName" id="userName"><span></span><br /> 密 码: <input type="text" name="userPwd" id="userPwd"><br/> <!-- <input type="submit"> --> <input type="button" id="btn" value="提交"> </form> <script> // http://127.0.0.1:3002/submit?userName=tom&userPwd=123 // URL地址栏拼接参数的形式给服务器传递数据 // 1. 获取页面中的标签对象 var btn = document.querySelector('#btn'); var userNmae = document.querySelector('#userName'); var userPwd = document.querySelector('#userPwd'); // 2. 给按钮注册事件 userName.onblur = function(){ var val = this.value; if(!val.trim()){ alert("用户名不能为空..."); return; // 中断代码向下执行 } var xhr = new XMLHttpRequest(); xhr.open('get', '/validate?userName=' + userName.value); // validate这个接口是用来判断用户名是否存在的 //get方式请求可以忽略请求头 // 设置请求体 xhr.send(null); // 因为get请求是通过URL地址栏拼接参数的形式传递数据,所以这里没有请求数据,需要写一个null // 监视异步对象的状态 xhr.onreadystatechange = function(){ if(xhr.status==200 && xhr.readyState==4){ userName.nextElementSibling.innerHTML = xhr.responseText; } } } </script> </body> </html>
3.使用AJAX异步对象发送POST请求
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>注册用户名</title> </head> <body> <form> 用户名: <input type="text" name="userName" id="userName"><span></span><br /> 密 码: <input type="text" name="userPwd" id="userPwd"><br/> <!-- <input type="submit"> --> <input type="button" id="btn" value="注册"> </form> <script> var btn = document.querySelector('#btn'); var userName = document.querySelector('#userName'); var userPwd = document.querySelector('#userPwd'); var val; userName.onblur = function(){ val = this.value; if(!val.trim()){ alert("用户名不能为空!"); return; } var xhr = new XMLHttpRequest(); xhr.open('post', '/validate'); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send('userName=' + val); xhr.onreadystatechange = function(){ if(xhr.status==200 && xhr.readyState==4){ console.log(xhr.responseText); userName.nextElementSibling.innerHTML = xhr.responseText; } } } // 点击按钮提交数据 btn.onclick = function(){ var xhr = new XMLHttpRequest(); xhr.open('post', '/submit'); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); var param = { "userName": val, "userPwd": userPwd.value, } obj = JSON.stringify(param); console.log(obj); xhr.send(obj); console.log(typeof obj); // console.log('userName=' + val +'&'+ 'userPwd=' + userPwd.value); xhr.onreadystatechange = function(){ if(xhr.status===200 && xhr.readyState==4){ alert("注册成功"); } } } </script> </body> </html>
4.服务端代码 app.js
// 1. 引入模块 const http = require('http') const path = require('path') const fs = require('fs') const querystring = require('querystring') const urlModule = require('url') // 2. 创建服务器对象 var server = http.createServer() // 3. 开启服务并监听端口 server.listen(3002,()=>{ console.log('the server is running at http://127.0.0.1:3002'); }) // 4.注册请求事件,监听请求 server.on('request',(req,res)=>{ var urlObj = urlModule.parse(req.url,true); var pathname = urlObj.pathname;// 获取请求路径 var method = req.method; var query = urlObj.query; if(method=='GET'&&pathname=='/index.html'){ fs.readFile(path.join(__dirname,'views/index.html'),(err,data)=>{ if(err) return res.end('404') res.end(data) }) }else if (method == 'GET' && pathname == '/register.html') { fs.readFile(path.join(__dirname, 'views/register.html'), (err, data) => { if (err) return res.end('404') res.end(data) }) } else if (method == 'GET' && pathname == '/submit') { var userName = query.userName; var userPwd = query.userPwd; fs.readFile(path.join(__dirname,'data.json'),'utf-8',(err,data)=>{ if(err) return res.end('404') var arr = JSON.parse(data); var flag = true; arr.some(item=>{ if(userName == item.userName){ flag = false; return true; } }) if(flag){ arr.push(query); fs.writeFile(path.join(__dirname,'data.json'),JSON.stringify(arr,null,' '),err=>{ res.writeHeader(200, { "Content-Type": "text/plain;charset=utf-8", "refresh": "3;url=/index.html" }) res.end("恭喜你,注册成功") }) }else { res.writeHeader(200, { "Content-Type": "text/plain;charset=utf-8", "refresh": "3;url=/register.html" }) res.end('你好倒霉啊,用户名已经被占用,亲,换一个吧') } }) }else if(method=='POST'&&pathname=='/submit'){ var str = '' req.on('data',chunk=>{ str += chunk; }) req.on('end',()=>{ var user = querystring.parse(str);// 将post过来的数据转换成对象 fs.readFile(path.join(__dirname,'data.json'),'utf-8',(err,data)=>{ if(err) return console.log(err.message); var arr = JSON.parse(data) var flag = true; arr.some(item=>{ if(item.userName == user.userName){ flag = false; return true; } }) if (flag) { arr.push(user); fs.writeFile(path.join(__dirname, 'data.json'), JSON.stringify(arr,null,' '), err => { res.writeHeader(200, { "Content-Type": "text/plain;charset=utf-8", "refresh": "3;url=/index.html" }) res.end("恭喜你,注册成功") }) } else { res.writeHeader(200, { "Content-Type": "text/plain;charset=utf-8", "refresh": "3;url=/register.html" }) res.end('你好倒霉啊,用户名已经被占用,亲,换一个吧') } }) }) }else if(method=='GET'&&pathname=='/validate'){ fs.readFile(path.join(__dirname,'data.json'),'utf-8',(err,data)=>{ if(err) return console.log(err.message); var arr = JSON.parse(data); var flag = true; arr.some(item=>{ if(query.userName==item.userName){ flag = false return true; } }) if(flag){ res.writeHeader(200,{ 'Content-Type':'text/plain;charset=utf-8' }) res.end('恭喜你,用户名可以使用') }else { res.writeHeader(200, { 'Content-Type': 'text/plain;charset=utf-8' }) res.end('抱歉,用户名已经被占用,请更换一个') } }) } else if (method == 'POST' && pathname == '/validate'){ var str = '' req.on('data', chunk => { str += chunk; }) req.on('end', () => { var user = querystring.parse(str);// 将post过来的数据转换成对象 fs.readFile(path.join(__dirname, 'data.json'), 'utf-8', (err, data) => { if (err) return console.log(err.message); var arr = JSON.parse(data) var flag = true; arr.some(item => { if (item.userName == user.userName) { flag = false; return true; } }) if (flag) { res.writeHeader(200,{ 'Content-Type':'text/plain;charset=utf-8' }) res.end("恭喜你,此用户名可以使用") } else { res.writeHeader(200, { "Content-Type": "text/plain;charset=utf-8" }) res.end('你好倒霉啊,用户名已经被占用,亲,换一个吧') } }) }) }else if(method=='GET'&&pathname=='/getData'){ fs.readFile(path.join(__dirname,'data.json'),'utf-8',(err,data)=>{ if(err) return res.end('404') res.end(JSON.stringify({ "code":200, "des":"请求成功", "data":JSON.parse(data) })) }) }else { res.end('404') } })
5.JSON数据 data.json
[
{
"userName": "tom",
"userPwd": "123"
},
{
"userName": "tom123",
"userPwd": "123"
},
{
"userName": "aaa",
"userPwd": "123"
},
{
"userName": "rose",
"userPwd": "123"
}
]