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);}
}