前端點滴(JS核心)(三)---- 使用 Ajax 實現多表聯動(優化)、XML、FromData對象、跨域請求

一、優化三表聯動

1. 將數據庫修改成文件

省市縣的數據,不會經常變動,基本上可以認爲是不變的數據。對於這樣的數據,最好不要存到數據庫,用文件存放也是一樣的,而且用文件存放還可以減輕數據庫的壓力。所以用文件把省市縣的數據存儲,然後去查文件。

文件關聯:
在這裏插入圖片描述
文件下載(city):
鏈接: https://pan.baidu.com/s/19s13smuDcTeaDTAU0UqG7Q
提取碼: 94md
複製這段內容後打開百度網盤手機App,操作更方便哦

2. 簡化 PHP 代碼 (控制層)

複製city文件夾到項目中:
在這裏插入圖片描述
查詢省、市、縣的時候都根據文件名去查找,並且約定瀏覽器請求的時候,要傳遞filename參數,參數的值就是文件名(實際上就是省市縣連接的關係,上述文件關係)。
所以:

PHP(06city.php)

<?php
//1. 判斷書否含有參數,沒有就表示獲取省份(文件名0),有就根據參數查找文件
$filename = isset($_GET['filename']) ? $_GET['filename'] : 0;  //php4-5語法形式
//$filename = $_GET['filename']??0;   //php7 語法形式

//2.根據參數進行文件查詢
echo file_get_contents('city/$filename.json');
//從PHP 5開始,FILE_USE_INCLUDE_PATH可用於觸發包含路徑搜索。

3. 修改 JavaScript 代碼

(1)加載省份

 var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
        if(xhr.readyState==4 && xhr.status==200){
            //接收服務器返回的數據
            var result = xhr.responseText;
            var res = JSON.parse(result);
            //console.log(res); //JS數組
            var sheng = document.getElementById('sheng');
            for(var i in res){
                var option = document.createElement('option');
                option.setAttribute('value', res[i].id);//參數就是id,根據id查找對應的文件(通過文件名)
                option.innerText = res[i].cn_name;
                sheng.appendChild(option);
            }
        }
    };
    xhr.open('get', '06city.php', true);
    xhr.send();

(2)加載對應的市

/* 切換sheng時,獲取其對應的id值,後通過對應的id值查詢文件(通過文件名) */
document.getElementById('sheng').onchange = function () {
		// 獲取 id
        var id = this.value; 
        xhr.onreadystatechange = function () {
            if(xhr.readyState==4 && xhr.status==200){
                //接收服務器返回的數據
                var result = xhr.responseText;
                var res = JSON.parse(result);

                var shi = document.getElementById('shi');
                //把市的option放到select中之前,先重置select裏面的內容
                shi.innerHTML = '<option value="0">--請選擇市--</option>';
                document.getElementById('xian').innerHTML = '<option value="0">--請選擇縣--</option>';
                for(var i in res){
                    var option = document.createElement('option');
                    option.setAttribute('value', res[i].id);
                    option.innerText = res[i].cn_name;
                    shi.appendChild(option);
                }
            }
        };
        //傳遞參數,查詢對應的文件名,從而找到文件
        xhr.open('get', '06city.php?filename='+id, true);
        xhr.send();
 }

(3)加載對應的區、縣

/* 切換shi時,獲取其對應的id值,後通過對應的id值查詢文件(通過文件名) */
 document.getElementById('shi').onchange = function () {
 		// 獲取 id
        var id = this.value;
        xhr.onreadystatechange = function () {
            if(xhr.readyState==4 && xhr.status==200){
                //接收服務器返回的數據
                var result = xhr.responseText;
                var res = JSON.parse(result);

                var xian = document.getElementById('xian');
                //把縣的option放到select中之前,先重置select裏面的內容
                xian.innerHTML = '<option value="0">--請選擇縣--</option>';
                for(var i in res){
                    var option = document.createElement('option');
                    option.setAttribute('value', res[i].id);
                    option.innerText = res[i].cn_name;
                    xian.appendChild(option);
                }
            }
        };
        xhr.open('get', '06city.php?filename='+id, true);
        xhr.send();
 }

4. 簡化 JavaScript 代碼(封裝函數)

//請求函數
function get(url,fn){
	var xhr = new XMLHttpRequest();
	xhr.onreadystatechange = function(){
		if(xhr.readyState == 4&&xhr.status == 200){
			var result = xhr.responseText;
			var res = JSON.parse(result);
			fn(res);
		}
	}
	xhr.open('get','url',true);
	xhr.send();
}
//返回數據處理函數
function callback(res,ele){
	for(var i in res){
		 var option = document.createElement('option');
         option.setAttribute('value', res[i].id);
         option.innerText = res[i].cn_name;
         ele.appendChild(option);
	}
}
//DOM操作節點函數
function $(id){
	return document.getElementById(id)
}
/* 獲取省份 */
/* 使用匿名會回調函數獲取數據,後進行調用處理 */
get('06city.php',function(data){
	chuli(data,$('sheng'));
})

/* 獲取市 */
$('sheng').onchange = function(){
	var id = this.value;
	get('06city.php?filename='+id,function(data){
		//重置市
        $('shi').innerHTML = '<option value="0">--請選擇市--</option>';
        //重置縣
        $('xian').innerHTML = '<option value="0">--請選擇縣--</option>';
        //數據處理
        chuli(data,$('shi'));
	})
}

/* 獲取區 */
$('shi').onchange = function(){
	var id = this.value;
	get('06city.php?filename='+id,function(data){
        //重置縣
        $('xian').innerHTML = '<option value="0">--請選擇縣--</option>';
        //數據處理
        chuli(data,$('xian'));
	})
}

寫的$、get函數做什麼項目都可以使用,可以將這兩個函數寫到一個js文件中。
所以根據上述的函數封裝就引出了所謂的 jQuery 庫,實際上就是 JavaScript 的函數封裝

二、XML

1. 什麼是 XML

XML(eXtensible Markup Language):可擴展標記語言
用於標記電子文件使其具有結構性的標記語言,可以用來標記數據、定義數據類型,是一種允許用戶對自己的標記語言進行定義的源語言。
xml也是一種標記(標籤)語言,它的側重點是描述數據,而相似的HTML主要用於展示數據。
標籤特點:

  • XML標籤可以自己定義(帶有語義化)
  • HTML標籤固定

意義:

  • XML用於存儲數據,用瀏覽器打開沒有特殊效果,就是一個樹狀結構
  • HTML用於展示數據,每個標籤都有各自的樣式。

2. XML 的媒介作用

在web開發領域,XML的作用主要是:

  • 存儲數據,充當小型數據庫;
  • 當做配置文件;
  • 當做兩種編程語言交互數據的中間媒介,類似JSON。

3. XML 實例

XML也是標籤語言,標籤可以自定義,但XML的語法更加嚴格。在編寫XML文件的時候,要注意下面幾點:

  • 文檔聲明:<?xml version='1.0' encoding='utf-8'?>,必須存在,寫在開頭。
  • 標籤必須閉合,即使是單標記標籤,如<age></age >
  • 屬性必須加引號
  • 區分大小寫
  • 文檔有且只有一個根標籤
/* 07XMLtest.xml */
<?xml version = '1.0' encoding = 'utf-8'?>
<student> <!- 一個根標籤 ->
    <stu>
        <name>yaodao</name>
        <age>25</age>
        <sex>男</sex>
    </stu> 
    <stu>
        <name>jack</name>
        <age>20</age>
        <sex>男</sex>
    </stu>
</student>

4. PHP 返回 XML 格式的數據

JavaScript

    <script type="text/javascript">
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function(){
            var res = xhr.responseXML;
            console.log(res);
        }
        xhr.open('get','08phpandXML.php',true);
        xhr.send();
    </script>

PHP(08phpandXML.php)

<?php
//必須指定header,告訴瀏覽器,返回的內容是xml格式
header('content-type:text/xml');
//讀取xml文件,然後返回
echo file_get_contents('07XMLtest.xml');

返回結果:
在這裏插入圖片描述

5. 瀏覽器處理 XML 格式數據

返回的結果可以當做document對象來使用。也就是說,可以調用getEle….系列方法,DOM中曾經學習過的大部分方法都可以使用。簡而言之,就是可以把返回的結果當做一個HTML文檔來處理。

 <script type="text/javascript">
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function(){
            var res = xhr.responseXML;
            console.log(res);
            var stus = res.getElementsByTagName('stu');
            document.write('<table border="1" width="300">')
            for(var i in stus){
                document.write('<tr>');
                document.write('<td>'+stus[i].children[0].innerHTML+'</td>');
                document.write('<td>'+stus[i].children[1].innerHTML+'</td>');
                document.write('</tr>');
            }
            document.write('</table>');
        }
        xhr.open('get','08phpandXML.php',true);
        xhr.send();
    </script>

三、FromData 對象

1. 什麼是 FromData 對象

FormData:字母意思就是表單數據,這是h5中新增的一個內置對象(構造器),它可以獲取任何類型的表單項的值,比如text/radio/checkbox/file/textarea,適用於獲取大量的表單項的值。常用於發送Ajax請求。
優點:簡單的代碼,就能將表單中所有類型的數據都收集到,包括文件域的內容,非常方便。
缺點:因爲是h5新增,所以IE9+才支持。

2. 使用 FromData 對象蒐集表當數據併發送異步請求

注意點:

  • 必須使用post請求,並使用FormData的時候,不用設置請求頭 xhr.setRequestHeader();
  • 有文件域,但是不用設置enctype
  • 獲取表單的內容使用$_POST,獲取文件域的內容使用$_FILES
  • 收集表單項的值是根據表單項的name值獲取的

HTML

<form name="myform">
    用戶名:<input type="text" name="username"><br>
    密 碼:<input type="password" name="pwd"><br>
    性 別:
    <input type="radio" name="sex" value="男" checked>男
    <input type="radio" name="sex" value="女" >女<br>
    愛 好:
    <input type="checkbox" name="hobby[]" value="喫飯">喫飯
    <input type="checkbox" name="hobby[]" value="睡覺">睡覺
    <input type="checkbox" name="hobby[]" value="看書">看書<br>
    圖 片:<input type="file" name="pic"><br>
    地 址:
    <select name="address">
        <option value="北京">北京</option>
        <option value="廣東">廣東</option>
        <option value="天津">天津</option>
    </select>
    <br>
    簡 介:<textarea name="introduce" cols="45" rows="3"></textarea><br>
    <input type="button" value="提交" id="btn">
</form>

PHP(09Form_Data.php)

<?php
// 將表單數據(文本數據)保存在post.txt文件中
file_put_contents('post.txt', print_r($_POST,true)); //返回php數據格式數據到文件中
// 將上傳文件信息保存在file.txt文件中
file_put_contents('file.txt', print_r($_FILES,true));

JavaScript

<script>
//找button按鈕,綁定單擊事件
    document.getElementById('btn').onclick = function () {
        /***** 收集表單數據 *****/
        var form = document.myform; //0級DOM
        var fd = new FormData(form); //獲取表單數據
        /***** 發送Ajax請求 *****/
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {

        };
        xhr.open('post', '09Form_Data.php');
        xhr.send(fd);
    };
</script>

結果:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

3. 使用 FromData 完成異步上傳

在使用FromData完成異步上傳後產生了兩個text(表單信息、上傳文件信息)信息文件,但是缺少了實例文件(上傳的文件)比如:圖片;文件;視頻…
所以進一步創建目錄保存上傳的文件
修改PHP(09Form_Data.php)

/* 創建文件夾保存上傳文件 */
<?php
/* 1、蒐集上傳文件信息以及表單信息 */
file_put_contents('post.txt', print_r($_POST,true)); 
file_put_contents('file.txt', print_r($_FILES,true));

/* 2、自動創建目錄保存上傳文件 */
$dir = './uploads/'.date('Y/m/');
if(!file_exists($dir)){
	mkdir($dir,0777,true); //0777表示最高權限
}
/* 3、制定不重複的文件名 */
//文件名
$filename = uniqid();
//後綴名
$png = strrchr($_FILES['pic']['name'], '.');  //獲取上傳文件信息中的文件名,後從‘.’開始截取到最後

//組合、放入、移動語法:move_uploaded_file(舊地址,新地址)
move_uploaded_file($_FILES['pic']['tmp_name'],$dir.$filename.$png)

效果:
在這裏插入圖片描述
在這裏插入圖片描述
擴展:
0777概念:

權限(二進制) r(可讀) w(可寫) x(可執行) 十進制
特殊權限位 0 0 0 0
owner(擁有者位) 1 1 1 7
group(同組用戶位) 1 1 1 7
other(其餘用戶位) 1 1 1 7

表示擁有者、同組用戶、其餘用戶都具有讀、寫、執行的權限。

特殊權限位說明:

  • setuid位, 如果該位爲1, 則表示設置setuid
  • setgid位, 如果該位爲1, 則表示設置setgid
  • sticky位, 如果該位爲1, 則表示設置sticky

setuid: 設置使文件在執行階段具有文件所有者的權限. 典型的文件是 /usr/bin/passwd。如果一般用戶執行該文件, 則在執行過程中, 該文件可以獲得root權限, 從而可以更改用戶的密碼。

setgid: 該權限只對目錄有效. 目錄被設置該位後, 任何用戶在此目錄下創建的文件都具有和該目錄所屬的組相同的組。

sticky bit: 該位可以理解爲防刪除位. 一個文件是否可以被某用戶刪除, 主要取決於該文件所屬的組是否對該用戶具有寫權限。

如果沒有寫權限, 則這個目錄下的所有文件都不能被刪除, 同時也不能添加新的文件。如果希望用戶能夠添加文件但同時不能刪除文件,則可以對文件使用sticky bit位。設置該位後, 就算用戶對目錄具有寫權限, 也不能刪除該文件。

4. 異步上傳實現進度條效果

(1)準備

因爲是本地,上傳速度非常快,所以上傳一個小文件看不出進度條。所以上傳大文件。上傳大文件就需要修改php.ini,主要修改三個max。

使用 wampserver
1)點擊wampserver圖標
2)選中PHP中的php.ini
3)對以下參數進行修改
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

(2)Ajax 對象中的 upload 屬性

代碼:
在這裏插入圖片描述

打印結果:
在這裏插入圖片描述
繼續打印xhr.upload:
在這裏插入圖片描述
添加onprogress事件,並打印事件對象:

document.getElementById('btn').onclick = function () {
        /***** 收集表單數據 *****/
        var form = document.myform; //0級DOM
        var fd = new FormData(form); //獲取表單數據
        /***** 發送Ajax請求 *****/
        var xhr = new XMLHttpRequest();
        // console.log(xhr);
        // console.log(xhr.upload);
        /* 綁定事件,打印事件對象 */
        xhr.upload.onprogress = function(el){
            console.log(el);
        }
        xhr.onreadystatechange = function () {

        };
        xhr.open('post', '09Form_Data.php');
        xhr.send(fd);
    };

打印結果:
在這裏插入圖片描述

(3)製作進度條

使用 H5 progress 標籤,製作進度條
在這裏插入圖片描述
修改上述代碼:

document.getElementById('btn').onclick = function () {
        /***** 收集表單數據 *****/
        var form = document.myform; //0級DOM
        var fd = new FormData(form); //獲取表單數據
        /***** 發送Ajax請求 *****/
        var xhr = new XMLHttpRequest();
        // console.log(xhr);
        // console.log(xhr.upload);
        var prog = document.getElementsByTagName('progress')[0];
        /* 綁定進程事件 */
        xhr.upload.onprogress = function(el){
            prog.setAttribute('value',el.loaded);
            prog.setAttribute('max',el.total);
            prog.style.display = 'block';
        }
        xhr.onreadystatechange = function () {

        };
        xhr.open('post', '09Form_Data.php');
        xhr.send(fd);
    };

結果:
在這裏插入圖片描述
在這裏插入圖片描述

四、跨域請求

1.前期準備

配置 wampserver 多域名(站點)
1)啓動wampserver(等待綠標)–> 點擊綠標找到Apache --> 使用記事本打開其中的 httpd-vhosts.conf 文件。
httpd-vhosts.conf 文件配置用於多個域名,注意: 原域名儘量不要動。
在這裏插入圖片描述
2)使用記事本打開Apache中的 httpd.conf 文件
由於httpd-vhosts.conf是擴展文件,要確保httpd-vhosts.conf的配置是被引用,有些版本默認是註釋的。ctrl+f搜索hosts,解其搜索結果下的 #
在這裏插入圖片描述
3)同樣是這個文件,ctrl+f搜索controls,修改搜索結果下的內容。
在這裏插入圖片描述
4)使用記事本打開C:\Windows\System32\drivers\etc路徑下的hosts文件,添加站點。注意: 站點要和1步驟中的自定義域名相同。
在這裏插入圖片描述
5)將所有的記事本保存,重啓wampserver,進行測試。
在各自存放文件的路徑中新建文件
在這裏插入圖片描述
在這裏插入圖片描述
6)打開瀏覽器在地址欄中輸入
在這裏插入圖片描述
在這裏插入圖片描述

2. 同源政策

1995年,同源政策由 Netscape(網景) 公司引入瀏覽器。目前,所有瀏覽器都實行這個政策。
最初,它的含義是指,A 網頁設置的 Cookie,B 網頁不能打開,除非這兩個網頁同源。所謂同源指的是三個相同。

  • 協議相同(http https)
  • 域名相同
  • 端口相同(默認80端口)

隨着互聯網的發展,同源政策越來越嚴格。目前,如果非同源,共有三種行爲受到限制。

  • Cookie無法讀取。
  • DOM 無法獲得。
  • AJAX 請求無效(可以發送,但瀏覽器會拒絕接受響應)。

3. 什麼是跨域請求

其實,瞭解了什麼是同源政策,就知道什麼是跨域請求了。
在發送Ajax請求的時候,請求的地址只要違反了同源政策,那麼就屬於跨域請求。
在這裏插入圖片描述
在這裏插入圖片描述
瀏覽器返回結果:
在這裏插入圖片描述
在這裏插入圖片描述

4. 實現跨域請求

(1)代理方式實現跨域請求

在這裏插入圖片描述
發送Ajax請求的時候,請求本網站的php文件,讓本網站的php文件去請求另外網站的內容。

www.ajaxtest.com:01kuayu.html
在這裏插入圖片描述
www.ajaxtest.com:01kuayu.php
在這裏插入圖片描述
www.jstest.com:01kuayu.php
在這裏插入圖片描述
結果:
在這裏插入圖片描述

(2)cors方式實現請求(設置訪問權限)

www.ajaxtest.com:02kuayu.html
在這裏插入圖片描述www.jstest.com:02kuayu.php
在這裏插入圖片描述
結果:
在這裏插入圖片描述

(3) 使用JSONP技術實現跨域請求

Jsonp(JSON with Padding) 是 json 的一種"使用模式",通俗的講,jsonp可以通過html標籤中的src屬性可以訪問另外域的內容,可以讓網頁從別的域名(網站)那獲取資料,即跨域讀取數據。
參考:https://www.runoob.com/json/json-jsonp.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章