AJAX和模板引擎

理解同步、异步,掌握ajax概念以及如何发起ajax请求,了解模板引擎及其简单实现原理

AJAX定义

  • AJAX 不是 JavaScript 的规范,它是”Asynchronous JavaScript and XML”的缩写,意思是用JavaScript执行 异步 网络请求.
  • AJAX 不是一门新的语言,而是对现有技术的综合利。
  • 简单说, AJAX 就是 浏览器 和 服务器 之间进行 异步交互 无需刷新页面 的技术。

说到这,让我们来了解一下 异步 的相关知识:

异步和同步

异步 的定义

异步 指的是某段程序执行时不会阻塞其他程序的执行,其表现形式为程序的执行顺序,不依赖程序本身的 书写顺序,相反为同步。
独立是异步的区别 ,省时是异步的理由。

生活中的例子

打电话是同步,发消息是异步。

异步的优势

异步 的优势在于不阻塞程序的执行,从而提升整体执行效率。

异步优势

那么如何在 浏览器 上使用 AJAX 呢

首先了解 AJAX 的原理:

AJAX原理

在现代浏览器上书写AJAX主要依靠XMLHttpRequest对象。

认识 XMLHttpRequest 对象

1
2
3
4
5
6
7
8
9
10
11
12
1. 什么是XMLHttpRequest对象?
XMLHttpRequest是浏览器的内置对象,用于在后台和服务器通信(交换数据),XMLHttpRequest 对象提供了在网页加载后与服务器进行通信的方法。由此我们可以实现对网页的部分更新,而不是刷新整个页面。
XMLHttpRequest 对象提供了对 HTTP 协议的完全的访问,包括做出 POST 和 HEAD 请求以及普通的 GET 请求的能力。XMLHttpRequest 可以同步或异步地返回 Web 服务器的响应,并且能够以文本或者一个 DOM 文档的形式返回内容。
2.XMLHttpRequest的主要作用:
- 在不重新加载页面的情况下更新网页
- 在页面已加载后从服务器请求数据
- 在页面已加载后从服务器接收数据
- 在后台向服务器发送数据
3.注意:
尽管名为 XMLHttpRequest,它并不限于和 XML 文档一起使用:它可以接收任何形式的文本文档。

让我们通过一个具体案例更清晰的了解它

点击按钮,获取后台数据,显示到浏览器上。(不刷新页面)

HTML代码

1
2
3
4
5
6
7
8
9
10
11
12
13
<body>
<input type="button" value="获取数据">
<table>
<thead>
<tr>
<th>姓名</th><th>头像</th><th>性别</th><th>年龄</th><th>爱好</th>
</tr>
</thead>
<tbody>
//接收数据,在这里输出
</tbody>
</table>
</body>

后台 php 代码

1
2
3
4
5
6
7
8
9
<?php
// 服务器告诉浏览器用什么样的方式解析读取到的内容
header("Content-Type:application/json;charset=UTF-8");
$content = file_get_contents('./jsoncase.json');
echo $content;
?>

JSON 数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[
{"name":"悠悠",
"photo":"./images/gg.jpg",
"sex":"男",
"age":18,
"hobby":"两只老虎"
},
{
"name":"小杨",
"photo":"./images/ss.jpg",
"sex":"男",
"age":43,
"hobby":"污妖王"
}
...
]

创建XMLHttpRequest对象

通过一行简单的JavaScript代码,我们就可以创建XMLHttpRequest对象。 在所有的现在浏览器(包括IE7):

在IE5和IE6中:

1
2
3
4
5
6
7
//如果你想把标准写法和IE写法兼容在一起,可以这么写:
var request;
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
} else {
request = new ActiveXObject('Microsoft.XMLHTTP');
}

具体代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// 1.获取按钮
var oBtn = document.querySelector("input");
//2.添加事件
oBtn.onclick = function () {
// 3.实例化对象
//var xhr= new XMLHttpRequest();(一般这样写就OK)
//兼容
var xhr;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
// 4.设置请求行
xhr.open('post','./jsonCase.php');//xhr.open(请求方式,请求地址,是否异步);默认为asny:true;即异步
// 5.设置请求头
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
// 6.设置请求正文(有格式key=value&key=value,如果是get请求,那么请求正文在url后面,请求正文的send方法为null)
xhr.send(null);
// 7.监听并处理响应
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
// console.log(xhr.responseText);
// 如何获取json中的数据
var result =JSON.parse(xhr.responseText);
// console.log(result);
var html= "";
for(var i =0;i<result.length;i++){
html+=
"<tr>"+
"<td>"+result[i].name+"</td>"+
"<td>"+"<img src="+result[i].photo+">"+"</td>"+
"<td>"+result[i].age+"</td>"+
"<td>"+result[i].height+"</td>"+
"<td>"+result[i].hobby+"</td>"+
"</tr>";//如果字符串负责,拼接字符串会很繁琐
}
// console.log(html);
document.querySelector('table').innerHTML= html;
}
}
}

注意事项

发送GET请求时

1
2
3
4
5
6
7
8
9
10
oBtn.onclick = function () {
//发送GET请求
//1.调用xhrt对象的open()方法建立一个连接
//①method参数:请求方式
//②url参数:请求的目标地址
//发送请求参数:附着在URL地址后面
xhr.open("get", "?userName=Tom2015");
//2.调用xhrt对象的send()方法发送请求数据
xhr.send();
};

发送POST请求

1
2
3
4
5
6
7
8
9
oBtn.onclick = function () {
//发送POST请求
//发送请求参数:将请求参数键值对以参数形式传递给send()方法
xhr.open("post", "./jsonCase.php");
//设置请求消息头为如下的值:
//Content-Type:application/x-www-form-urlencoded
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send("userName=Jerry2015&userPwd=123456");
};

这一点详情见我以前总结的相关于请求报文和响应报文的文章

如何更简单的发起 ajax 请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
jQuery Ajax操作函数
> $.ajax()
配置项
type 默认值: "GET")。请求方式 ("POST""GET"), 默认为 "GET"
url 默认值: 当前页地址。发送请求的地址。
data 发送到服务器的数据。将自动转换为请求字符串格式。
processData 默认情况下,通过data选项传递进来的数据,如果是一个对象都会处理转化成一个查询字符串
dataType 预期服务器返回的数据类型。如果不指定,jQuery 将自动根据 HTTP 包 MIME 信息来智能判断
如果为json:它首先尝试使用 JSON.parse()。如果浏览器不支持,则使用一个函数来构建。
如果为jsonp 类型,那么当从服务器接收到数据时,实际上是用了 <script> 标签而不是 XMLHttpRequest 对象。
如果为text 和 xml 类型返回的数据不会经过处理。数据仅仅简单的将 XMLHttpRequest 的 responseText 或 responseHTML 属性传递给 success 回调函数。
timeout设置请求超时时间(毫秒)。
> $.get(url,data,success(data, textStatus),dataType);
> $.post(url,data,success(data, textStatus),dataType);

上面我们发现,拼接字符串会很繁琐,那么如何让拼接字符串变得更简单

使用模板引擎

1.模板引擎介绍

1
2
3
4
JavaScript 模板引擎是将 HTML 结构从包含它们的内容中分离的方法。使用模板引擎的原因是当页面比较复杂的时候。
拼接字符串麻烦且容易出错。JavaScript模板引擎可以帮我们解决这个问题。
拼接字符串是麻烦但是如果对于简单的布局 就别用模板引擎
如果页面比较复杂 或者需要的数据的页面比较麻烦 那么才用模板引擎

2.常见的模板引擎

1.art-template(腾讯)

2.BaiduTemplate(百度)

3.Velocity(阿里)

4.Handlebars

每个模板都有自己的语法,详情见各自的readme.md,下面只阐述一下art-template的原生语法,方便初学者入门

3.art-template 语法

1
2
3
4
5
6
7
8
9
10
<1>.引入模板引擎的包
<2>.创建模板
模板中的变量就是对象的属性
<%title%> 不输出
<%=title%> 输出到html上
<3>.获取数据
<4>.把数据和模板绑定起来
template(id,对象) 返回绑定好的html字符串

4.深入探究模板的原理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
==>1 //利用正则表达式的方法,找到字符串中特定自负,替换为数据对应的值
<script>
// 有一个字符串
var html = '我叫<% name %>,我今年<% age %>岁了,我在<% school %>学习';
// 数据
var data = {
name: '小明',
age: 18,
school: '某大'
}
var reg = /<%\s*([^%>]\S+)\s*%>/;
// /<%\s*([^%>]\S+)\s*%>/这是整个表达式 <% name %> <% age %> <% school %>
// ([^%>]\S+) 这是一个子表达式 name age school
// exec() match() test() 方法属于正则表达式的三个方法
// exec()匹配一个正则表达式 如果该表达式还有子表达式 那么会把整个表达式的匹配的结果和子表达式匹配的结果 当作数组返回
var match = reg.exec(html);
// console.log(match);
html = html.replace(match[0], data[match[1]]);
console.log(html);
match = reg.exec(html);
// console.log(match);
html = html.replace(match[0], data[match[1]]);
console.log(html);
match = reg.exec(html);
// console.log(match);
html = html.replace(match[0], data[match[1]]);
console.log(html);
match = reg.exec(html);
console.log(match); //如果没有匹配的结果之后返回null
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
==>2 //简化代码
<script>
// 有一个字符串
var html = '我叫<% name %>,我今年<% age %>岁了,性别<%sex%>,我在<% school %>学习';
// 数据
var data = {
name: '小明',
age: 18,
school: '某大',
sex: '男'
}
var reg = /<%\s*([^%>]\S+)\s*%>/;
var match = null;
while (match = reg.exec(html)) {
html = html.replace(match[0], data[match[1]]);
}
console.log(html);
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
==>3 //封装函数
<p></p>
<script type="text/template" id="tmpl">
我叫<span><% name %></span>,我今年<span><% age %></span>岁了,我在
<% school %>学习;
</script>
<script>
// 数据
var cc = {
name: '小明',
age: 18,
school: '某大'
}
// 封装template函数
function template(id, data) {
var html = document.getElementById(id).innerHTML;
var reg = /<%\s*([^%>]\S+)\s*%>/;
var match = null;
while (match = reg.exec(html)) {
html = html.replace(match[0], data[match[1]]);
}
return html;
}
var html = template('tmpl', cc);
// console.log(html);
document.querySelector("p").innerHTML = html;
</script>