Ajax_简介: 异步的 JS 和 XML_原生写 ajax 分析其原理_jquery_ajax_art-template
AJAX
Asynchronous JavaScript And XML
通过 AJAX 可以在 浏览器中向 服务器 发送异步请求
一种 使用现有标准的 新方法,而非新语言
- XML
可扩展标记语言
被设计用来传输和存储数据
被 JSON 替代,JSON 内容更少,解析更方便
和 HTML 类似,不同的是
- HTML 都是预定义标签
- XML 全部是自定义标签,用来表示一些数据
- AJAX 工作原理
相当于在 用户 和 服务器 之间加了一个中间层(AJAX 引擎)
使得 用户操作 和 服务器响应 异步化
1. 原生 AJAX(不要通过 webstorm 启动页面,否则会发生 跨域 错误)
// 1. 创建 xhr 对象
const xhr = new XMLHttpRequest();
// 2. 设置事件监听
xhr.onreadystatechange = function(){ // 会监听 readyState 值的变化
if (xhr.readyState === 2) {
console.log(xhr.status);
console.log(xhr.getResponseHeader('Content-Type'));
}
if (xhr.readyState === 3) {
console.log(xhr.responseText);
}
if(xhr.readyState === 4 && xhr.status === 200){ // 响应成功
console.log(xhr.responseText); // 响应数据
};
};
/****
前端面试题:
readyState
0 xhr 对象创建成功,但是 xhr.open() 还未调用
1 open() 已经调用了,但是还未调用 send() (意味着还没有发送请求,还可以设置请求头信息)
2 send() 已经调用了,接收到部分响应数据(响应首行、响应头,没接到响应体)
3 接收到了响应体数据(如果响应体较小,或者纯文体,在此阶段就全部接收完了)
4 接收完全部的响应体数据(数据较大,或者音视频资源)
****/
// 3. 设置请求信息 设置请求方式、地址、参数
xhr.open("GET", "http://localhost:3000/ajax?username=jack&age=18");
// 还能设置请求头 xhr.setRequestHeader();
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
/****
必须要设置 请求头 标准规范(有三种常见规范),否则不会解析请求参数
chrome 和 FireFox 第二次及以后默认走协商缓存,状态码 304,且还会向服务器发送请求
ie 第二次及以后 get 请求 默认走强制缓存,状态码 200,且不会向服务器发送请求
需求: 股票 需要实时更新信息,此时就不能从缓存里找
解决 ie 的缓存问题:
让每一次的请求不一样
只要请求不一样,就不会走缓存
xhr.open("GET", "http://localhost:3000/ajax?username=jack&age=18&date="+Date.now());
****/
// 4. 发送请求
xhr.send();
// post 发送数据 必须以 urlencode 格式,即查询字符串去掉?,即 key=value的方式,多个键值对之间以 & 连接
- 源码实例
- node.js 服务器
index.js
const express = require('express'); const app = express(); app.use(express.static("public"));
app.use(express.urlencoded({extended: true})); app.get("/", (request, response)=>{
response.sendFile("./public/idnex.html");
}); // 原生 ajax 的 get 路由
app.get("/ajax", (request, response)=>{
console.log('----get 接收的 浏览器数据: ');
console.log(request.query); // {}
console.log(request.body); // get 请求体 始终为空
console.log('----'); response.send({name: '服务器 get 响应', line: 15});
}); // 原生 ajax 的 post 路由
app.post("/ajax", (request, response)=>{
console.log('----post 接收的 浏览器数据: ');
console.log(request.query); // {} 可以有 请求字符串
console.log(request.body); // post请求体 数据{ username: 'jack', age: '18' }
console.log('----'); response.send({name: '服务器 post 响应', line: 21});
}); /**************** 端口号 3000, 启动服务器 ***************/
app.listen(3000, err=>console.log(err?err:'\n\n服务器已启动: http://localhost:3000\n\t\tHunting Happy!'));- 浏览器前端代码
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>原生 ajax</title>
</head> <body> <button id="get_btn">get</button>
<button id="post_btn">post</button> <script type="text/javascript" src="js/index.js"></script>
</body>
</html>
js/index.js
window.addEventListener('DOMContentLoaded', function () {
const getBtn = document.getElementById("get_btn");
const postBtn = document.getElementById("post_btn"); getBtn.onclick = function () {
// 1. 创建 xhr 对象
const xhr = new XMLHttpRequest(); // 2. 设置事件监听
xhr.onreadystatechange = function () {
if (xhr.readyState === 2) {
console.log(xhr.status); // 状态码
console.log(xhr.getResponseHeader('Content-Type')); // 请求头 信息
};
if (xhr.readyState === 3) {
console.log(xhr.responseText); // 服务器响应 数据
};
if(xhr.readyState === 4 && xhr.status === 200){
console.log(xhr.responseText); // 服务器响应 数据
};
}; // 3. 设置请求方式、请求地址、请求参数
xhr.open("GET", "http://localhost:3000/ajax?username=get&get=get"); // 4. 设置请求头
xhr.setRequestHeader('get-x', 'get'); // 5. 发送请求
xhr.send('request=get&get=get'); // get 请求体为空,所以这里传的参数,无效
}; postBtn.onclick = function () {
// 1. 创建 xhr 对象
const xhr = new XMLHttpRequest(); // 2. 设置事件监听
xhr.onreadystatechange = function () {
if (xhr.readyState === 2) {
console.log(xhr.status);
console.log(xhr.getResponseHeader('Content-Type'));
}
if (xhr.readyState === 3) {
console.log(xhr.responseText);
}
if(xhr.readyState === 4 && xhr.status === 200){
console.log(xhr.responseText);
};
}; // 3. 设置请求方式、请求地址、请求参数
xhr.open("POST", "http://localhost:3000/ajax?username=post&post=post"); // 4. 设置请求头
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded'); // 5. 发送请求
xhr.send('request=post&post=post');
};
}, false);
2. jQuery 中的 AJAX 请求
- node.js 服务器
index.js
const express = require('express'); const app = express(); app.use(express.static("public"));
app.use(express.urlencoded({extended: true})); app.get("/", (request, response)=>{
response.sendFile("./public/idnex.html");
}); // 原生 ajax 的 get 路由
app.get("/jquery_ajax", (request, response)=>{
console.log('----get 接收的 浏览器数据: ');
console.log(request.query); // {}
console.log(request.body); // get 请求体 始终为空
console.log('----'); response.send({name: '服务器 get 响应', line: 15});
}); // 原生 ajax 的 post 路由
app.post("/jquery_ajax", (request, response)=>{
console.log('----post 接收的 浏览器数据: ');
console.log(request.query); // {} 可以有 请求字符串
console.log(request.body); // post请求体 数据{ username: 'jack', age: '18' }
console.log('----'); response.send({name: '服务器 post 响应', line: 21});
}); /**************** 端口号 3000, 启动服务器 ***************/
app.listen(3000, err=>console.log(err?err:'\n\n服务器已启动: http://localhost:3000\n\t\tHunting Happy!'));- 浏览器前端代码
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>jQuery 中的 ajax</title>
</head> <body> <button id="get_btn">get</button>
<button id="post_btn">post</button> <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery_ajax.js"></script>
</body>
</html>
index.js
window.addEventListener('DOMContentLoaded', function () {
const getBtn = document.getElementById("get_btn");
const postBtn = document.getElementById("post_btn"); getBtn.onclick = function () {
$.ajax('http://localhost:3000/jquery_ajax', {
method: 'GET', // 可以直接换成 POST,库解决好了请求头和兼容等一系列问题
data: {
getrequest:'Browser',
age:10
},
headers: {
'get-xxx': 'xxxx'
},
success: function (server_info) {
console.log('请求成功的回调函数');
console.log(server_info); // 自动将 json 字符串 转换成 JSON 对象
},
error: function (err) {
console.log('请求失败的回调函数');
console.log(err);
}
});
}; postBtn.onclick = function () {
$.get( // 可以直接换成 post,库解决好了请求头和兼容等一系列问题
'http://localhost:3000/jquery_ajax',
{postrequest:'Browser', age:26},
function (server_info) {
console.log(server_info);
});
};
}, false);
三级联动 选择(省-市-县)
- 服务器 index.js
const express = require('express');
const promiseConnect = require('./db/connectDB.js');
const citiesModel = require('./models/userModel.js');
const app = express(); (async ()=>{
const ret = await promiseConnect;
console.log(ret); app.use(express.static("public"));
app.use(express.urlencoded({extended: true})); app.get("/", (request, response)=>{
response.sendFile("./public/index.html");
}); // 省 的 get 路由
app.get("/province", async (request, response)=>{
try{
const province = await citiesModel.find({"level": 1}, {"province": 1, "name": 1, "_id": 0});
response.json({code: 200, data: province});
}catch(err){
console.log(err);
response.json({code: 404, data: '网络不稳定,请刷新重试'});
};
}); // 市 的 get 路由
app.get("/city", async (request, response)=>{
try{
const {province} = request.query;
const city = await citiesModel.find({province, "level": 2}, {"city": 1, "name": 1, "_id": 0});
response.json({code: 200, data: city});
}catch(err){
console.log(err);
response.json({code: 404, data: '网络不稳定,请刷新重试'});
};
}); // 县 的 get 路由
app.get("/county", async (request, response)=>{
try{
const {province, city} = request.query;
const county = await citiesModel.find({province, city, "level": 3}, {"county": 1, "name": 1, "_id": 0});
response.json({code: 200, data: county});
}catch(err){
console.log(err);
response.json({code: 404, data: '网络不稳定,请刷新重试'});
};
});
})().catch(err=>console.log(err)); /**************** 端口号 3000, 启动服务器 ***************/
app.listen(3000, err=>console.log(err?err:'\n\n服务器已启动: http://localhost:3000\n\t\tHunting Happy!'));- 浏览器前端 index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>三级联动-省-市-县</title>
<link rel="stylesheet" href="./css/index.css">
</head> <body>
<div id="outer_box">
<select id="province">
<option>请选择省份</option>
</select>省 <select id="city">
<option>请选择市</option>
</select>市 <select id="county">
<option>请选择区(县)</option>
</select>区(县)
</div> <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript" src="./js/jquery_ajax.js"></script>
</body>
</html>index.css
html, body {
width: 100%;
height: 100%; color: #000;
background: #b9c2a4;
background-size: cover; /* 指定背景图片大小 */
} /*************************************************/
#outer_box {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
} #outer_box select {
width: 152px;
font-size: 16px;
background-color: #aec57e;
cursor: pointer;
}- 选择省份
为了避免重排 重绘,使用拼串,最后一次追加
- 选择市
监听 表单的 change 事件
- 选择县
- jquery_ajax.js
$(function () {
const $province = $("#province");
const $city = $("#city");
const $county = $("#county"); // 进入页面 首先渲染省份
$.get("http://localhost:3000/province", function({code, data}){
if(code === 200){
let htmlStr = '<option>请选择省份</option>';
data.forEach(each=>{
/* <option value="44">广东省</option> */
htmlStr += `<option value="${each.province}">${each.name}</option>`;
});
$province.html(htmlStr);
}else{
alert(data); // 网络不稳定,请刷新重试
};
}); // 省 改变出现 市
$province.on("change", function(){
const province = this.value; /* <option value="11">北京</option> */
$.get('/city', {province}, function({code, data}){
if(code === 200){
let htmlStr = '<option>请选择市</option>';
data.forEach(each=>{
/* <option value="03">深圳市</option> */
htmlStr += `<option value="${each.city}">${each.name}</option>`;
});
$city.html(htmlStr);
}else{
alert(data); // 网络不稳定,请刷新重试
};
});
}); // 市 改变出现 县
$city.on("change", function(){
const province = $province.val(); /* <option value="11">北京</option> */
const city = $city.val(); /* <option value="undefined">鞍山市</option> */
console.log({province, city});
$.get('/county', {province, city}, function({code, data}){
if(code === 200){
let htmlStr = '<option>请选择市</option>';
data.forEach(each=>{
/* <option value="06">宝安区</option> */
htmlStr += `<option value="${each.county}">${each.name}</option>`;
});
$county.html(htmlStr);
}else{
alert(data); // 网络不稳定,请刷新重试
};
});
});
});在 jQuery 中 $.get("http://localhost:3000/city", function({code, data}){}); 对于同一域名,可以简写为
- $.get("/city", function({code, data}){});
1. 引入 第三方 js库 art-template
<script type="text/javascript" src="./js/template-web.js"></script>
2. 新建 <script> 标签,并设置 id 以供渲染
3.
源码由上方代码改变
- index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>jQuery 中的 ajax</title>
<link rel="stylesheet" href="./css/index.css">
</head> <body>
<div id="outer_box">
<select id="province">
<option>请选择省份</option>
</select>省 <select id="city">
<option>请选择市</option>
</select>市 <select id="county">
<option>请选择区(县)</option>
</select>区(县)
</div> <script type="text/html" id="templateScript">
<option>{{firstOption}}</option>
{{each data}}
<option value="{{$value[name]}}">{{$value.name}}</option>
{{/each}}
</script> <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript" src="./js/template-web.js"></script>
<script type="text/javascript" src="./js/jquery_ajax.js"></script> <!-- 注意编写顺序 -->
</body>
</html>- jquery_ajax.js
$(function () {
const $province = $("#province");
const $city = $("#city");
const $county = $("#county"); // 进入页面 首先渲染省份
$.get("http://localhost:3000/province", function({code, data}){
if(code === 200){
const htmlStr = template(
'templateScript',
{data, firstOption: '请选择省份', name: 'province'}
);
$province.html(htmlStr);
}else{
alert(data); // 网络不稳定,请刷新重试
};
}); // 省 改变出现 市
$province.on("change", function(){
const province = this.value; /* <option value="11">北京</option> */
$.get('/city', {province}, function({code, data}){
if(code === 200){
const htmlStr = template(
'templateScript',
{data, firstOption: '请选择市', name: 'city'}
);
$city.html(htmlStr);
}else{
alert(data); // 网络不稳定,请刷新重试
};
});
}); // 市 改变出现 县
$city.on("change", function(){
const province = $province.val(); /* <option value="11">北京</option> */
const city = $city.val(); /* <option value="undefined">鞍山市</option> */
$.get('/county', {province, city}, function({code, data}){
if(code === 200){
const htmlStr = template(
'templateScript',
{data, firstOption: '请选择区县', name: 'county'}
);
$county.html(htmlStr);
}else{
alert(data); // 网络不稳定,请刷新重试
};
});
});
});
Ajax_简介: 异步的 JS 和 XML_原生写 ajax 分析其原理_jquery_ajax_art-template的更多相关文章
- Ajax:异步的JS和XML
1.Ajax1) AJAX 是 Asynchronous JavaScript And XML 的简称.直译为,异步的JS和XML.2) AJAX的实际意义是,不发生页面跳转.异步载入内容并改写页面内 ...
- 原生js写Ajax
//原生js写ajax就像打电话 //打电话分下面4步//1.拿出手机//2.拨号//3.说话//4.挺对方说话 //ajax也分下面4步//1.创建ajax对象//2.连接到服务器//3.发送请求( ...
- PHP, Python, Node.js 哪个比较适合写爬虫?
PHP, Python, Node.js 哪个比较适合写爬虫? 1.对页面的解析能力2.对数据库的操作能力(mysql)3.爬取效率4.代码量推荐语言时说明所需类库或者框架,谢谢.比如:python+ ...
- 用原生JavaScript写AJAX
//原生js写ajax就像打电话 //打电话分下面4步//1.拿出手机//2.拨号//3.说话//4.听对方说话 //ajax也分下面4步//1.创建ajax对象//2.连接到服务器//3.发送请求( ...
- JS与APP原生控件交互
"热更新"."热部署"相信对于混合式开发的童鞋一定不陌生,那么APP怎么避免每次升级都要在APP应用商店发布呢?这里就用到了混合式开发的概念,对于电商网站尤其显 ...
- PhoneGap或者Cordova框架下实现Html5中JS调用Android原生代码
PhoneGap或者Cordova框架下实现Html5中JS调用Android原生代码 看看新闻网>看引擎>开源产品 0人收藏此文章, 发表于8小时前(2013-09-06 00:39) ...
- JS入门学习,写一个简单的图片库
<!-- 新手刚开始学JS,每天坚持写点东西 坚持下去,希望能有所进步 . 加油~~ --> <!DOCTYPE html> ...
- JS里写入(混写)php asp
原文:JS里写入(混写)php asp JS里写入(混写)php 方法1:<Br> <script language="javascript"> docum ...
- PHP原生写的生成图片缩略图类
PHP原生写的生成图片缩略图类,本文以京东商品图片为例,分别生成三种不同尺寸的图片.调用方法很简单只要传参数高度和宽度,及新图片的名称. 引入缩略图类 include_once 'ImageResiz ...
随机推荐
- Nuxt.js学习
SSR服务端渲染 之前用vue做项目时,在浏览器中查看网页源码,是没有具体内容的,只有一个标签,用服务端渲染的话,查看网页源码数据都会显示出来,所以有利于SEO,能够被搜索到. Nuxt.js是做Vu ...
- 第十二节: 总结Quartz.Net几种部署模式(IIS、Exe、服务部署【借助TopSelf、服务类】)
一. IIS部署 比如在MVC框架中集成了Quartz.Net定时调度,此时该调度系统会随着MVC框架被挂在IIS下,IIS会进程回收,所以大部分开发都会遇到Quartz挂在IIS下一段时间不好用. ...
- ArcGis Classic COM Add-Ins插件开发的一般流程 C#
COM add-ins是我对这种开发方式的称呼,Esri的官方文档里称其为“Extending ArcObject”或者“Classic COM extensibility”,Esri所称的addin ...
- 在Unity3D里使用WinForm
之前给一个游戏写过MOD,功能大概是在游戏里可以打开一个编辑器,然后可以直接在编辑器里修改到游戏数据. 编辑器UI的实现部分,一开始用的是原生GUI,即OnGUI部分,这种方式虽然最简洁,也不用引用任 ...
- 给Myeclipse配置tomcat服务器
1.安装好Tomcat 7.x服务器 2.window->perference,在搜索框中搜索Tomcat: 3.将MyEclipse自带的Tomcat及其他的Tomcat服务器禁用: 4.启用 ...
- 玩转ubuntu之初体验
安装的是ubuntu16.04.1,分区和具体细节就不多说了,非常简单 安装完之后要做的几件事: 1.设置root密码 #设置root密码 sudo passwd root 2.检查并更新系统 #ub ...
- Concurrent下的线程安全集合
1.ArrayBlockingQueue ArrayBlockingQueue是由数组支持的线程安全的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序.这是一个典型的“有界缓存区”,固定 ...
- Linux常用命令总结-软件测试面试专用
- Python的真和假
python和其他编程语言一样,,,0是假,非0是真,,python 一切皆对象,真假是每个对象的属性.像数据结构,,空的数据结构是False. eg: "spam" True & ...
- 【原创】大数据基础之Zookeeper(2)源代码解析
核心枚举 public enum ServerState { LOOKING, FOLLOWING, LEADING, OBSERVING; } zookeeper服务器状态:刚启动LOOKING,f ...