0721 NOTE
1.ajax通信基础
var xhr = new XMLHttpRequest(); //xhr全称XMLHttpRequest,无刷新发起浏览器请求
xhr.addEventListener("load",loadHandler);
xhr.open("GET","http://localhost:4001?a=1&b=2");
xhr.send();
function loadHandler(e){
}
GET和POST的区别:
GET和POST都是向服务器传送数据,但是
GET需求重点为获取,因此不能向服务器发送消息,但是能通过地址栏用search的方式携带给服务器
POST需求重点:发送传输数据,传输数据完成后,会确认数据传输完成情况
2.浏览器回退时,GET不会再发送请求而POST会再次提交请求
3.GET产生的URL地址会被记录下来,而POST不会
4.GET请求会被浏览器主动cache(缓存),而POST不会(除非手动设置)
5.GET请求只能进行url编码,而POST支持多种编码方式。
6.GET参数通过URL传递,POST放在Request body中。
7.对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
GET产生一个TCP数据包;POST产生两个TCP数据包。
对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200;
而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200
//server.js
var http = require("http");
var querystring=require("querystring");
http.createServer((req,res)=>{
var data = "";
req.on("data",function(_data){
data += _data; //讲获取的二进制数据流转化为字符串
})
req.on("end",function(){
var requery=querystring.parse(decodeURIComponent(req.url.split("?")[1])); //url中获取数据
// console.log(req.method);
if(req.method.toUpperCase() === "POST"){
try {
// console.log("aaa");
data = JSON.parse(data); //用此方法解析querystring字符串会抛出异常,随后走错误处理语句
} catch (e) {
data = querystring.parse(data);
}
}
// console.log(requery);
// console.log(req);
// encodeURIComponent() 字符串转换为URI编码格式
// decodeURIComponent() 解码,URI编码格式转换为字符串
// console.log(req.url); //获取所接收消息地址后缀内容
console.log(data);
res.writeHead("200",{ //响应头,允许5500端口跨域访问
"Access-Control-Allow-Origin":"http://localhost:5500",
"Content-Type":"text/html;charset=utf-8"
// "Content-Type":"application/json;charset=utf-8" //返回消息为json格式字符串
})
res.end("你瞅啥!") //返回消息
})
}).listen(8080)
//index
var str = JSON.stringify({name:"kaige",say: "瞅你咋地!"});
var xhr = new XMLHttpRequest(); //xhr全称XMLHttpRequest,无刷新发起浏览器请求 //使用http协议发起对xml的请求
xhr.addEventListener("load", loadHandler); //加载服务器所发消息
xhr.open("POST", "http://localhost:8080"); //GET传输:?name=kaige&sex=男
xhr.send(str);
function loadHandler(e) {
console.log(xhr.response); //接收返回的信息
// console.log("瞅你咋地!"); //测试是否连接成功
}
2.fetch
fetch函数获得一个promise对象,因此可以使用promise方法,可以then,也可以使用async和await
// fetch("http://10.9.41.171:8080?name=kaige&say=我又回来了").then(function(res){ //fetch获得一个promise
// // console.log(res);
// // console.log(res.text()); //打印promise
// res.text().then(function(data){
// console.log(data);
// })
// })
// init();
// async function init(){
// var res = await fetch("http://10.9.41.171:8080?name=kaige&say=我又回来了");
// var data = await res.text();
// console.log(data);
// }
// fetch("http://10.9.41.171:8080?name=kaige&say=我又回来了").then(async res=>{ //async await 特征:等待 滞留
// var data = await res.text();
// console.log(data);
// }) //以上传输方式为GET
// fetch("http://10.9.41.171:8080?name=kaige&say=我又回来了",{method:"POST",body:JSON.stringify({name:"凯哥",say:"瞅你咋地!"})}).then(async res=>{
// var data = await res.json(); //此处转为json是因为返回的数据格式为json格式字符串
// console.log(data);
// })
// init();
// async function init(){
// var res = await fetch("http://10.9.41.171:8080",{method:"POST",body:JSON.stringify({name:"凯哥",say:"瞅你咋地!"})});
// var data = await res.json();
// console.log(data);
// }
3.商品菜单切换案例
/*css*/
.icons{
padding: 5px 20px;
height: 42px;
border:1px solid #666;
float: left;
font-size: 12px;
margin: 3px 5px;
line-height: 40px;
outline: 1px solid transparent;
}
.icons>.imgIcon{
width: 40px;
height: 40px;
float: left;
}
<script type = "module">
import Icon from "./js/Icon.js";
var xhr = new XMLHttpRequest(); //xhr全称XMLHttpRequest,无刷新发起浏览器请求 //使用http协议发起对xml的请求
xhr.addEventListener("load", loadHandler); //加载服务器所发消息
xhr.open("POST", "http://localhost:8080"); //GET传输:?name=kaige&sex=男
xhr.send();
function loadHandler(e) {
var arr=JSON.parse(xhr.response);
arr.forEach(item=>{
var icon=new Icon("goods",item);
icon.appendTo('body');
})
}
</script>
//goods.js
var arr = [
{ id: 1001, title: "亮黑色", icon: "./img/SKU-1-亮黑色.jpg", price: 6398 },
{ id: 1002, title: "夏日胡杨", icon: "./img/SKU-2-夏日胡杨.jpg", price: 7698.00 },
{
id: 1003,
icon: "./img/SKU-3-秋日胡杨.jpg",
title: "秋日胡杨",
price: 9098.00
},
{ id: 1004, title: "釉白色", icon: "./img/SKU-7-Mate40e(釉白色).jpg", price: 6398 },
{ id: 1005, title: "秘银色", icon: "./img/SKU-5-秘银色.jpg", price: 7798 },
{
id: 1007,
title: 'Mate40e(釉白色)',
icon: './img/SKU-7-Mate40e(釉白色).jpg',
price: 5698.00
},
{ id: 1008, title: "Mate40e秘银色", icon: "./img/SKU-8-Mate40e(秘银色).jpg", price: 6298 },
{ id: 1009, title: "Mate40亮黑色", icon: "./img/SKU-9-Mate40e(亮黑色).jpg", price: 6498 },
{ id: 1010, title: "Mate40(釉白色)", icon: "./img/SKU-10-Mate40(釉白色).jpg", price: 6498.00 },
{
id: 1011,
title: 'Mate40(秘银色)',
icon: './img/SKU-8-Mate40e(秘银色).jpg',
price: 6498
},
];
var http = require("http");
var querystring=require("querystring");
http.createServer((req,res)=>{
var data = "";
req.on("data",function(_data){
var router = req.url.split("?")[0];
router = router.slice(-1) === "/" ? router.slice(0,-1) : router;
data += _data; //获取的二进制数据流转化为字符串
})
req.on("end",function(){
var requery=querystring.parse(decodeURIComponent(req.url.split("?")[1])); //url中获取数据
console.log(requery);
if(req.method.toUpperCase() === "POST"){
try {
data = JSON.parse(data); //用此方法解析querystring字符串会抛出异常,随后走错误处理语句
} catch (e) {
data = querystring.parse(data);
}
}
res.writeHead("200",{ //响应头,允许5500端口跨域访问
"Access-Control-Allow-Origin":"*",
"Content-Type":"text/html;charset=utf-8"
})
res.end(JSON.stringify(arr)) //返回消息
})
}).listen(8080)
//Icon.js
export default class Icon{
elem;
data;
static prevList={};
constructor(name,_data){
this.name=name;
this.elem=document.createElement("div");
this.elem.className="icons"
this.elem.innerHTML=`<img class='imgIcon'><span class='span'></span>`
this.setData(_data);
this.elem.addEventListener("click",e=>this.clickHandler(e));
}
appendTo(parent){
if(typeof parent==="string") parent=document.querySelector(parent);
parent.appendChild(this.elem);
}
setData(_data){
if(!_data) return;
this.data=_data;
this.elem.firstElementChild.src=_data.icon;
this.elem.lastElementChild.textContent=_data.title;
}
clickHandler(e){
if(Icon.prevList[this.name]){
Icon.prevList[this.name].style.border="1px solid #666";
Icon.prevList[this.name].style.outline="1px solid transparent";
}
Icon.prevList[this.name]=e.currentTarget;
Icon.prevList[this.name].style.border="2px solid #FF0000";
Icon.prevList[this.name].style.outline="none";
}
}
4.三级联动菜单案例
<link href="./node_modules/bootstrap/dist/css/bootstrap.css" rel="stylesheet">
<script src="./node_modules/jquery/dist/jquery.js"></script>
<script src="./node_modules/bootstrap/dist/js/bootstrap.js"></script>
<script type="module">
import Menu from "./js/Menu.js";
var list = [];
init();
function init() {
for (var i = 0; i < 3; i++) {
var menu = new Menu();
menu.appendTo("body");
menu.addEventListener(Menu.MENU_CHANGE_EVENT, changeHandler);
list.push(menu);
}
ajax("/province")
}
function ajax(router, data = null) {
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", loadHandler);
xhr.open("POST", "http://localhost:8080" + router);
xhr.send(data ? JSON.stringify(data) : null);
}
function loadHandler(e) {
var data = JSON.parse(this.response);
switch (this.responseURL.split("/").pop()) {
case "province":
list[0].setData(data)
break;
case "city":
list[1].setData(data)
break;
case "county":
list[2].setData(data)
break;
}
}
function changeHandler(e) {
if (list.indexOf(this) === 0) ajax("/city", { provinceId: e.ids })
else if (list.indexOf(this) === 1) ajax("/county", { cityId: e.ids })
}
</script>
//Main.mjs
import City from "./City.mjs"; //菜单中信息数据,此文档中省略
import http from "http";
export default class Server{
constructor(){
http.createServer((req,res)=>this.createServerHandler(req,res)).listen(8080);
}
async createServerHandler(req,res){
var router=req.url.split("?")[0];
router=router.slice(-1)==="/" ? router.slice(0,-1) : router;
var data= await this.getData(req);
if(data)data=JSON.parse(data);
res.writeHead(200,{
"Access-Control-Allow-Origin":"*",
"Content-Type":"text/html;charset=utf-8"
})
if(req.url.includes("favicon.ico")) return res.end();
this.sendData(router,res,data);
}
getData(req){
return new Promise(function(resolve,reject){
var data="";
req.on("data",function(_data){
data+=_data;
})
req.on("end",function(){
resolve(data);
})
})
}
sendData(router,res,data){
switch(router){
case "/province":
res.end(JSON.stringify(City["86"]));
break;
case "/city":
res.end(JSON.stringify(City[data.provinceId]));
break;
case "/county":
res.end(JSON.stringify(City[data.cityId]));
break;
}
}
}
new Server();
import Component from "./Component.js";
export default class Menu extends Component{
static MENU_CHANGE_EVENT="menu_change_event";
constructor(){
super();
this.elem.innerHTML=`
<button class='btn btn-danger'></button>
<button class='btn btn-danger dropdown-toggle' data-toggle="dropdown"> <span class="caret"></span></button>
<ul class="dropdown-menu"></ul>
`
this.elem.className='btn-group'
this.bn=this.elem.querySelector(".btn")
this.ul=this.elem.querySelector("ul");
this.ul.style.maxHeight="200px";
this.ul.style.overflow="auto"
this.ul.addEventListener("click",e=>this.clickhandler(e));
}
setData(_data){
var str="";
for(var prop in _data){
str+=`<li><a href='javascript:void(0)' ids='${prop}'>${_data[prop]}</a></li>`; //href='javascript:void(0)':不能点击
}
this.elem.lastElementChild.innerHTML=str;
var evt=new Event("click",{bubbles:true});
this.ul.firstElementChild.firstElementChild.dispatchEvent(evt);
}
clickhandler(e){
if(e.target.nodeName!=="A") return;
// console.log(e.target);
this.bn.textContent=e.target.textContent;
var evt=new Event(Menu.MENU_CHANGE_EVENT);
evt.value=this.bn.textContent;
evt.ids=e.target.getAttribute("ids");
this.dispatchEvent(evt);
}
}
5.聊天室案例
/*css*/
textarea{
width: 1200px;
height: 600px;
resize: none;
background-color: white;
overflow: auto;
}
input{
height: 30px;
line-height: 30px;
font-size: 25px;
}
input[name=msg]{
width: 800px;
}
button{
width: 80px;
height: 30px;
}
<textarea disabled></textarea>
<form action="#">
<input type="text" name="user">说:
<input type="text" name="msg">
<button type="submit">提交</button>
</form>
<script>
var form,textarea;
init()
function init(){
form=document.querySelector("form");
textarea=document.querySelector("textarea");
form.addEventListener("submit",submitHandler);
setInterval(()=>ajax("/getmsg"),500)
}
function submitHandler(e){
e.preventDefault();
var fd=new FormData(form);
var obj={}
fd.forEach((item,key)=>{
obj[key]=item;
});
form.children[1].value="";
ajax("/sendmsg",obj);
}
function ajax(router,data=null){
var xhr=new XMLHttpRequest();
xhr.addEventListener("load",loadHandler);
xhr.open("POST","http://10.9.41.171:8080"+router);
data? xhr.send(JSON.stringify(data)) : xhr.send();
}
function loadHandler(e){
var arr=JSON.parse(this.response);
textarea.value=arr.reduce((value,item)=>{
return value+item.user+"说:"+item.msg+"\n";
},"")
textarea.scrollTop=textarea.scrollHeight;
}
</script>
var http=require("http");
var querystring=require("querystring");
var arr=[];
http.createServer((req,res)=>{
var data="";
req.on("data",function(_data){
data+=_data;
})
req.on("end",function(){
var router=req.url.split("?")[0]
router=router.slice(-1)==="/" ? router.slice(0,-1) :router;
if(data) data=JSON.parse(data);
res.writeHead(200,{
"Access-Control-Allow-Origin":"*",
"Content-Type":"text/html;charset=utf-8"
})
if(req.url.includes("favicon.ico")) return res.end();
if(router==="/sendmsg"){
arr.push(data);
res.end(JSON.stringify(arr));
}else if(router==="/getmsg"){
res.end(JSON.stringify(arr));
}else{
res.end();
}
})
}).listen(8080);