Ajax-03
模板引擎原理
正则回顾
- 区分正则方法和字符串方法
- 正则方法
- test()
- exec()
- 字符串方法
- match()
- replace()
- split()
- search()
- 正则方法
正则方法由正则表达式调用;字符串方法由字符串调用;
-
exec方法
- 功能:使用正则表达式匹配字符串,返回值中包含匹配的结果
- 特点:
- 一次只能匹配一个结果
- 再次调用将匹配下一个结果
- 没有更多匹配则返回null
- 如果正则表达式中有捕获(小括号),则返回值中包括捕获的结果
-
replace方法
- 功能:字符串替换
- 特点:
- 可以使用正则表达式进行匹配搜索
- 可以使用函数完成高级的替换
<script>/*// 正则对象的方法正则表达式.test(字符串);正则表达式.exec(字符串);// 字符串方法字符串.match();字符串.replace();字符串.split();字符串.search();*/// let str = 'this is a ES6 that is a H5';// let reg = /xxxx/g;// -------------------------------------- test -------------------------------------// 正则表达式.test(字符串); -- 检查字符串是否和正则表达式匹配。返回值是true或者false// let str = 'this is a ES6 that is a H5';// let reg = /[a-z]/g;// console.log(reg.test(str)); // 检查字符串中是否包含小写字母,true// -------------------------------------- exec -------------------------------------// 正则表达式.exec(字符串); // -- 完成正则匹配,并且把匹配的结果取出来。如果不匹配,则返回null// -- 特点是一次只匹配一个结果。如果想匹配下一个结果,则需要再次调用exec方法// let str = '2345 1122 5678 8990';// let reg = /\d\d\d\d/g; // /\d{4}/g;// /[0-9]{4}/g;// console.log(reg.exec(str)); // ["2345", index: 0, ....]// console.log(reg.exec(str)); // ["1122", index: 5, ....]// console.log(reg.exec(str)); // ["5678", index: 10, ....]// console.log(reg.exec(str)); // ["8990", index: 15, ....]// console.log(reg.exec(str)); // null// -------------------------------------- 分组捕获 -------------------------------------// 分组也叫做捕获。正则表达式中的小括号表示捕获// let str = '1313 1122 4949 8899 7789';// // let reg = /(\d)\1\d\d/g; // 希望第1个数字和第2个数字相同// // let reg = /(\d)\1(\d)\2/g; // 希望第1个数字和第2个数字相同。并且第3个数字和第4个数字相同// let reg = /(\d)(\d)\1\2/g; // 希望第1个数字和第3个数字相同。并且第2个数字和第4个数字相同// console.log(str.match(reg));// -------------------------------------- exec+分组 -------------------------------------// let str = '1234 2344 6767 8899';// let reg = /\d\d(\d)\d/g;// console.log(reg.exec(str)); // ['1234', '3' ....] // 数组的第一个元素是匹配的结果。第二个元素是分组的结果// console.log(reg.exec(str)); // ['2344', '4' ....]// console.log(reg.exec(str)); // ['6767', '6' ....]// console.log(reg.exec(str)); // ['8899', '9' ....]// console.log(reg.exec(str)); // null// -------------------------------------- replace -------------------------------------let str = 'ES6 and H5';let reg = /\d/g;// 把字符串中的数字换成 x // console.log(str.replace(reg, 'x'));/*使用函数来完成复杂的替换如下:函数的形参x,表示每次匹配到的结果函数中return的值,就是替换后的结果*/let result = str.replace(reg, function (x) {return parseInt(x) + 1;});console.log(result);</script>
实现模板引擎
<script type="text/html" id="test"><p>{{title}}</p><p>{{content}}</p>
</script><script>let data = {title: '锦瑟',content: '锦瑟无端五十弦,一弦一柱思华年。'}// 自定义函数,实现模板引擎的功能。体会一下真实的模板引擎的实现原理function template (tplId, data) {// 1. 根据模板的id,找到元素,并获取元素里面的HTMLlet html = document.getElementById(tplId).innerHTML;// console.log(html);// 2. 替换HTML中的 {{xxx}} 为真实的数据// html = html.replace('{{title}}', data.title);// html = html.replace('{{content}}', data.content);let reg = /{{(\w+)}}/g; // \w 表示大小写字母、数字、下划线let result = '';while (result = reg.exec(html)) {html = html.replace(result[0], data[result[1]]);}// 3. 将替换好的结果返回即可return html;}// 使用template函数,完成模板引擎功能let str = template('test', data);console.log(str);
</script>
新闻列表案例
略,参见代码
原生XHR对象
发送GET方式的请求
// 使用 xhr 对象发送GET方式的请求
/*1. 创建 xhr 对象2. 调用 xhr.open() 函数。设置请求方式和url3. 调用 xhr.send() 函数。发送请求4. 监听 xhr.onreadystatechange 事件。只要ajax的状态改变就会触发> 第4步,可以放到第3步或者第2步之前> ajax的状态,后续讲解*/let xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks');
xhr.send();
xhr.onreadystatechange = function () {// console.log(111);// 这个事件触发了多次,因为输出看到,有三次结果// xhr.responseText; // 接收响应结果if (xhr.readyState === 4) {console.log(xhr.responseText);}
};
Ajax的状态
- 上图中ajax的状态,一共有5个,分别用数字 0、1、2、3、4表示。
- 我们只需要关系最后一个状态即可,因为此时,我们可以接收到完整的结果
- 代码中,我们使用
xhr.readyState
属性表示ajax的状态
关于onreadystatechange
事件的触发时机:
- 很明显的,ajax的状态值发生了改变,比如从0变化到1、或者从1变化到2…的时候,会触发
- 如果服务器返回大量的数据,浏览器是分块接收数据的,当接收到的数据量发生变化的时候,也会触发
xhr发送带参数的GET请求
- GET方式的请求参数,叫做查询字符串,英文 querystring
- 查询字符串的格式
key=value&key=value....
- 发送get请求的时候,查询字符串和接口之间,使用
?
隔开
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks?id=1&bookname=西游记');
之前,$.ajax里面的请求参数,之所以可以写对象形式,是因为函数内部,把对象转成了查询字符串格式。
xhr发起POST方式的请求
和GET方式的两个区别:
- 必须在open和send之间,加一个请求头
- 查询字符串的位置变化为send的参数
// 1. 创建 xhr 对象
let xhr = new XMLHttpRequest();
// 2. 注册 onreadystatechange 事件
xhr.onreadystatechange = function () {if (this.readyState === 4 && this.status === 200) {let res = JSON.parse(this.responseText);console.log(res);}
}
// 3. 调用open,设置请求方式和url
xhr.open('POST', 'http://www.liulongbin.top:3006/api/addbook');
// 4. POST方式,要设置请求头 --- 和GET方式不一样的一处
// 下面一行代码的意思,告诉服务器,前端提交的数据是什么类型的。表示是查询字符串类型
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// 5. 调用send,发送请求
// xhr.send('key=value&key=valuye.......');
xhr.send('bookname=唐诗三百首&author=老汤&publisher=黑马出版社');
URL编码
// 编码
encodeURI('红&黑');
// "%E7%BA%A2&%E9%BB%91"
encodeURIComponent('红&黑');
// "%E7%BA%A2%26%E9%BB%91"// 解码
decodeURI('%E7%BA%A2&%E9%BB%91');
// "红&黑"
decodeURIComponent("%E7%BA%A2%26%E9%BB%91");
// "红&黑"
在实际开发中,需要对中文及需要编码的特殊符号进行编码:
使用的编码函数:
- encodeURI() — 能够对中文进行编码
- encodeURIComponent() — 能够对中文和特殊符号进行编码(&=)
封装
思路:
- 模拟jQuery中的 $.ajax()
步骤:
- 定义空的函数,设置一个形参
- 模拟$.ajax() ,调用函数,并传递一个对象形式的参数
- 函数内部:编写原生的代码
- 无论是GET方式还是POST方式,我们都需要将服务器返回的结果传递给success
- 判断是GET还是POST方式,然后写对应的 open和send
- 将对象形式的请求参数(data),处理成查询字符串
定义与调用函数
// 模拟 $.ajax() ,自己封装一个实现ajax请求的函数/*option 是一个对象option.type 表示请求类型option.url 表示请求的urloption.data 表示请求参数option.success() 表示一个处理服务器返回结果的函数*/
function ajax (option) {}// 调用函数
ajax({type: 'post', // GET或POSTurl: 'http://www.liulongbin.top:3006/api/addbook',data: {bookname: 'aaa', author: 'bbb', publisher: 'ccc'},success: function (res) {console.log(res);}
});
写基本的代码
function ajax (option) {let xhr = new XMLHttpRequest();xhr.onreadystatechange = function () {}xhr.open();xhr.send();
}
将服务器返回的结果传递给success
function ajax (option) {let xhr = new XMLHttpRequest();xhr.onreadystatechange = function () {if (this.readyState === 4 && this.status === 200) {let x = JSON.parse(this.responseText);option.success(x); // 调用success函数,把服务器返回的结果传递给它}}xhr.open();xhr.send();
}
针对GET和POST分别写open和send方法
function ajax (option) {let xhr = new XMLHttpRequest();xhr.onreadystatechange = function () {if (this.readyState === 4 && this.status === 200) {let x = JSON.parse(this.responseText);option.success(x); // 调用success函数,把服务器返回的结果传递给它}}// 判断,GET和POST方式单独完成if (option.type === 'GET') {xhr.open('GET', option.url);xhr.send();} else if (option.type === 'POST') {xhr.open('POST', option.url);xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');xhr.send();}
}
将对象形式的data处理成querystring
function ajax (option) {let xhr = new XMLHttpRequest();xhr.onreadystatechange = function () {if (this.readyState === 4 && this.status === 200) {let x = JSON.parse(this.responseText);option.success(x); // 调用success函数,把服务器返回的结果传递给它}}// 先处理查询字符串,把传递进来的 对象形式的data,处理成查询字符串格式// {bookname: 'aaa', author: 'bbb', publisher: 'ccc'}// ===> bookname=aaa&author=bbb&publiser=ccclet arr = [];for (let key in option.data) {// key 表示对象的 键// option.data[key] 表示对象的值// arr.push('key=value');arr.push(key + '=' + option.data[key]); // ['bookname=aaa', 'author=bbb', ...]}let querystring = arr.join('&'); // bookname=aaa&author=bbb&publiser=ccc// 判断,GET和POST方式单独完成if (option.type === 'GET') {xhr.open('GET', option.url + '?' + querystring);xhr.send();} else if (option.type === 'POST') {xhr.open('POST', option.url);xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');xhr.send(querystring);}
}
优化-请求方式不区分大小写
function ajax (option) {let xhr = new XMLHttpRequest();xhr.onreadystatechange = function () {if (this.readyState === 4 && this.status === 200) {let x = JSON.parse(this.responseText);option.success(x); // 调用success函数,把服务器返回的结果传递给它}}// 先处理查询字符串,把传递进来的 对象形式的data,处理成查询字符串格式// {bookname: 'aaa', author: 'bbb', publisher: 'ccc'}// ===> bookname=aaa&author=bbb&publiser=ccclet arr = [];for (let key in option.data) {// key 表示对象的 键// option.data[key] 表示对象的值// arr.push('key=value');arr.push(key + '=' + option.data[key]); // ['bookname=aaa', 'author=bbb', ...]}let querystring = arr.join('&'); // bookname=aaa&author=bbb&publiser=ccc// 定义变量,接收并处理请求方式let method = option.type.toUpperCase(); // 把请求方式转成大写// 判断,GET和POST方式单独完成if (method === 'GET') {xhr.open('GET', option.url + '?' + querystring);xhr.send();} else if (method === 'POST') {xhr.open('POST', option.url);xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');xhr.send(querystring);}
}