一、請求後端的JSON數據 JSON是前後端通信的交互格式,JSON(JavaScript Object Notation, JS 對象標記) 是一種輕量級的數據交換格式。 JSON是互聯網各個後臺與前代溝通必備格式,取代了原來的XML。 XML數據格式特別“噁心”,現在市場上99%以上的數據格式都 ...
一、請求後端的JSON數據
JSON是前後端通信的交互格式,JSON(JavaScript Object Notation, JS 對象標記) 是一種輕量級的數據交換格式。
JSON是互聯網各個後臺與前代溝通必備格式,取代了原來的XML。
XML數據格式特別“噁心”,現在市場上99%以上的數據格式都是JSON。
工作中都是後端(Java、PHP、Node)給我們提供JSON格式的數據,然後我們前端用Ajax去請求得到JSON數據,將JSON數據渲染在前端頁面中。但是伺服器給我們返回的數據是字元串JSON,因此沒辦法打點調用屬性,下麵我們要學習如何解析後端給我們返回的JSON。
1.1 JSON解析方法1
獲取PHP中的JSON介面數據:
l 會發現伺服器給我們返回的數據是字元串JSON,因此沒辦法打點調用屬性
l PHP中可以將數組變為JSON,使用方法json_encode(數組)
json_db.php後端提供JSON數據:
<?php header("Content-type","application/json"); //用數組模擬,然後給客戶端返回JSON格式的數據 $arr = array("result"=> array( array("name" => "李白", "age" => 31, "sex"=>"男"), array("name" => "蘇軾", "age" => 32, "sex"=>"男"), array("name" => "王安石", "age" => 33, "sex"=>"男"), array("name" => "杜甫", "age" => 34, "sex"=>"男"), array("name" => "李清照", "age" => 35, "sex"=>"女") ) ); echo json_encode($arr); //將數組變為JSON ?>
前端請求php提供的介面,得到數據渲染在頁面
$.get("php/json_db.php", function(data){ var dataObj = JSON.parse(data); //將後端返回的字元串轉為JSON對象 //迴圈遍歷輸出 for(var i = 0; i < dataObj.result.length;i++){ var arr = dataObj.result[i]; //上樹 $("ul").append("<li>"+ arr.name + arr.age + arr.sex +"</li>") console.log(dataObj.result[i].age) console.log(dataObj.result[i].sex) } }) JSON.parse() 將JSON形式的字元串轉換為JSON對象 JSON.stringify() 將JSON對象轉換為字元串
獲取資料庫中的數據,以JSON的格式返回給前端:
data_db.php後端提供JSON數據:
<?php //連接資料庫,參數:資料庫地址、用戶名、密碼 mysql_connect('localhost', 'root', '123456'); //選擇要操作的資料庫 mysql_select_db("student"); //設置編碼 mysql_query("SET NAMES utf8"); //寫執行插入的SQL語句,保存到資料庫的表中 $sql = "SELECT * FROM gz0902"; //執行SQL語句,會返回成功插入的結果(條數) $result = mysql_query($sql); $arr = array(); //空數組,迴圈遍歷添加進來的 //迴圈遍歷賦值,添加到數組 while($row = mysql_fetch_array($result)){ array_push($arr, $row); } //輸出JSON $resultJSON = array("result" => $arr); echo json_encode($resultJSON); ?>
前端解析JSON
$.get("php/data_db.php", function(data){ //將JSON形式的字元串轉為真的JSON對象 var dataObj = typeof data == "object" ? data : JSON.parse(data); for(var i = 0; i < dataObj.result.length;i++){ var arr = dataObj.result[i]; $("ul").append("<li>"+ arr.name + arr.age + arr.sex +"</li>") console.log(dataObj.result[i].age) console.log(dataObj.result[i].sex) } })
1.2 JSON解析方法2
概述:eval()是系統預設的函數,是window對象方法,因此可以省略window直接使用。
eval()函數可以將字元串變為語句,把它作為JavaScript代碼執行。
eval()儘量少用,但是由於相容性好,所以該用的時候也要用
JavaScript為什麼不推薦使用eval?
https://www.zhihu.com/question/20591877
var str = "alert(1+2+3)"; console.log(eval(str)); var data = "({a:100,b:200})"; var data = "{a:100,b:200}"; console.log(eval("("+ data +")")) var fun = "function fun(){alert(1)};fun()"; console.log(eval(fun)) $.get("php/json_db.php", function(data){ //將JSON形式的字元串轉為真的JSON對象 var dataObj = eval("(" + data + ")"); })
1.3 JSON解析方法3
第三種方法:使用JS的內置構造函數new Function()。
參數:從第一個開始到倒數第二個都是形參,最後一個參數是執行的程式。
Function()函數能把字元串變為語句:
var sum = new Function("a","b","c","return a+b+c"); console.log(sum(3,4,5)); // 等價於 function sum(a,b,c){ return a+b+c; } $.get("php/json_db.php", function(data){ //將JSON形式的字元串轉為真的JSON對象 var dataObj = (new Function("return" + data)()); console.log(dataObj) })
二、B/S結構
概述:Ajax這門技術它遵循“同源策略”,也就說Ajax不能跨域。
同源策略:它是由Netscape提出的一個著名的安全策略,現在所有支持JavaScript的瀏覽器都會使用這個策略。
所謂的同源策略:功能變數名稱、協議、埠相同。
當一個瀏覽器的兩個tab頁分別打開:百度和谷歌的頁面
當瀏覽器的百度tab頁執行一個腳本的時候會檢查這個腳本是屬於哪個頁面的,
即檢查是否同源,只有和百度同源的腳本才會被執行。
如果非同源,那麼在請求數據時,瀏覽器會在控制臺中報一個異常,提示拒絕訪問。
跨域:其實就是訪問不在同一個伺服器上的數據,就形成了跨域。
比如:老師的伺服器IP是192.168.1.100,但是訪問某同學的伺服器中的文件,造成了跨域,會報錯。
2.1 Ajax不能跨域
概述:Ajax不能跨域,就比如我們的程式,不能獲取百度、淘寶、京東伺服器的數據。
<script type="text/javascript"> $.get("http://127.0.0.88/result.txt", function(data){ console.log(data) }) </script>
提示:剛纔模擬兩個伺服器之間請求數據,會發現Ajax不能跨域。
2.2 JSONP跨域
跨域請求數據也是可以的,只不過Ajax這技術不行,而JSONP這種數據格式可以進行跨域。很多年前,瀏覽器是沒有跨域限制的,可以正常跨域,瀏覽器為了安全和隱私限制了Ajax跨域。
我們可以通過一些數據手段解決:
為什麼使用跨域?當請求不在同一個伺服器數據的時候就用跨域,或者偷數據的時候。
實現方式:HTML中用script標簽引用這個js文件,其實就是對引用文件的函數執行,此時函數定義在HTML中。
JSONP原理就是:將函數執行的部分,放到了伺服器上面。
<script type="text/javascript"> function fun(data){ console.log(data) } </script> <script src="http://127.0.0.88/fun_info.txt"></script>
提示:這是老師的本地靜態頁面,當訪問某個同學伺服器的時候,返回的數據來源於某同學伺服器。
將函數執行的部分放在伺服器上。當自己伺服器想獲取其他伺服器上面的數據,你必須聲明一個和其他伺服器上同名的函數。
這是http://127.0.0.88/fun_info.txt的數據:
fun({"name":"陳雪凝","age":16, "sex":"女"});
提示:怎麼實現的?
答:script標簽當中的src屬性指向一個地址,發起了一次請求。
JSONP的優缺點:
優點:
l 與利用XHR對象發送Ajax請求不同,JSONP可以跨越同源策略;
l JSONP的相容性好,可以在眾多瀏覽器中運行。
缺點:
l 只支持GET一種類型的HTTP請求,應用場景有限;
l 調用失敗時缺少必要的提示信息,不方便排查問題;
l 存在一定的安全風險,但可以使用Referer和Token校驗進行規避;
l 不便於控制;
l 沒有回調函數的功能。
2.3原生JSONP跨越請求數據
<body> <button id="btn">發起請求(JSONP)</button> </body> <script type="text/javascript"> var btn = document.getElementById("btn"); //函數的定義的 function fun(data){ console.log(data) } //發起請求,獲取到函數執行部分 btn.onclick = function(){ //創建script標簽,並指定請求數據地址 var oscript = document.createElement('script'); oscript.src = "http://127.0.0.88/fun_info.txt"; //上樹 document.body.appendChild(oscript); //過河拆橋,拿完下樹 document.body.removeChild(oscript); } </script>
提示:script標簽發起一次請求後,就可以獲取到數據,然後讓元素下樹,不影響返回的數據。
Url中的callback對應的是函數的名。
提示:如果想獲取別人伺服器上的JSONP數據,你必須聲明一個和別人伺服器上的同名函數(也可以改名)
<script type="text/javascript"> function fetchJSON_comment98(data){ console.log(data) } </script> <!-- <script type="text/javascript" src="http://127.0.0.88/result.txt"></script> --> <script src="http://127.0.0.88/fun_info.txt"></script> <script src="https://sclub.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=598283&score=1&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1"></script>
2.4原生JSONP函數封裝
概述:封裝一個函數,這個函數的作用就是跨域請求別人伺服器的數據,用戶只需要傳進來,url和函數名。
<script type="text/javascript"> var btn = document.getElementById("btn"); function JSONP(url, callback){ //給傳進來的匿名函數起名,並定義在全局 window.fun = callback; //創建DOM var oscript = document.createElement('script'); oscript.src = url; //上樹 document.body.appendChild(oscript); //過河拆橋,拿完下樹 document.body.removeChild(oscript); } //發起請求 btn.onclick = function(){ JSONP("http://127.0.0.88/fun_info.txt", function(data){ console.log(data); //data數據是從函數執行部分傳過來的 }) } </script>
2.5 jQuery的JSONP跨域
概述:jQuery對JSONP進行了封裝,jsonCallback就是傳進去的函數名字
獲取某個伺服器的JSON數據:
$.ajax({ url:"http://127.0.0.88/fun_info.txt", dataType:"jsonp", jsonpCallback:"fun", //函數名 success:function(data){ console.log(data) } })
獲取京東評論的數據:
$.ajax({ url:"https://sclub.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=598283&scor e=1&sortType=5&page=0&pageSize=10", dataType:"jsonp", jsonpCallback:"fetchJSON_comment98", success:function(data){ console.log(data) } })
用jQuery跨域的時候,url中的callback後面是函數的名稱,也可以自己修改函數名。
如果url的callback後面是?號,不用寫jsonpCallback回調函數,jQuery會隨機的命名函數。
$.ajax({ url:"https://sclub.jd.com/comment/ productPageComments.action?callback=?&productId=598283&score=1&sortType=5&page=0&pageSize=10", dataType:"jsonp", success:function(data){ console.log(data) } })
下麵就是jQuery隨機的函數名。
2.6三級聯動
<body> <select id="province"></select> <select id="city"></select> <select id="area"></select> </body> <script type="text/javascript" src="js/jquery-2.2.4.min.js"></script> <script type="text/javascript"> $.get("data/city.txt",function(data){ //轉JSON對象 var dataObj = JSON.parse(data); //迴圈所有數據,讓省份上樹 $.each(dataObj.all, function(key,value){ // console.log(key,value); var $option = $("<option>"+ value.name +"</option>"); $("#province").append($option); }); //當省的數據發送變化時,執行以下方法 var cityArr = []; $("#province").on("change", function(){ //拿到當前選擇的省的名字 var pro = $("#province option:selected").text(); //遍歷省,得到市 $.each(dataObj.all, function(item,val){ if(val.name == pro){ for(var i = 0; i < val.city.length;i++){ $("<option>" + val.city[i].name + "</option>").appendTo('#city'); } cityArr.push(val.city) //遍歷得到區 $.each(val.city[0].area, function(index,val){ $("<option>" + val + "</option>").appendTo('#area'); }) } }) }) //當市改變時觸發,改變區‘ $("#city").on("change", function(){ $("#area").empty(); //清空內容 //獲取當前被選中的城市名字 var city = $("#city option:selected").text(); for(var i = 0; i < cityArr[0].length;i++){ if(cityArr[0][i].name == city){ $.each(cityArr[0][i].area, function(index, val){ $("<option>" + val + "</option>").appendTo('#area'); }) } } }) //頁面載入初始化城市數據 $("#province").triggerHandler('change'); }) </script>
三、效果
3.1載入完畢顯示-原生的套路
<style type="text/css"> div{ width: 300px; height: 300px; background: url('./images/loading.gif') no-repeat; } img{display: none;} </style> <body> <div> <img src="./images/19.png" > </div> </body> <script type="text/javascript"> var img = document.getElementsByTagName('img')[0]; //當圖片載入完畢後,顯示 img.onload = function(){ img.style.display = 'block'; } </script>
3.2載入完畢顯示-jquery的套路
Image是系統當中內置的構造函數,因此可以直接使用,返回的是一個img元素對象;
<body> <div id="box"></div> </body> <script type="text/javascript" src="js/jquery-1.12.4.min.js"></script> <script type="text/javascript"> // var img = document.createElement('img'); var img = new Image(); img.src = "./images/18.png"; //載入完畢上樹 $(img).load(function(){ $(this).appendTo($('#box')); }) </script>
四、聊天室
聊天室製作思路:
用戶點擊登錄把輸入的用戶名傳給Login.php,Login.php接收後正則驗證用戶名是否合法,如果不合法給前端返回一個-1,exit返回,
前端接收到返回是-1就提醒用戶重新輸入,如果合法就開啟會話session_start(),並且存儲用戶名,$_SESSION[name]=$name;且返回一個1給前端,
前端收到是1就登錄成功,跳轉到聊天頁面(有中文記得聲明utf-8編碼),再開啟會話,讀取用戶名,判斷用戶按下回車時,將用戶名和輸入內容寫進資料庫,
資料庫再開會話接受數據,連接資料庫,插入數據,執行這條數據$result=mysql_query($sql);如果他是真就返回1,否則返回-1,
聊天頁面請求里的函數接受到時1就把輸入框清空,起初有滾動條且捲動值是自己的高,開一個定時器,清空聊天框的內容,向資料庫get請求JSON數據,資料庫連接,
讀取數據表且排序(記得聲明JSON)執行這個表,聲明一個數組,他有一個最大的鍵,迴圈拿去數據表中的項,存在一個變數,將這個變數push到我們聲明的數據最大的鍵里,
它的值就是一個數組,在pint_r輸出,記得把這個數組轉成JSON,聊天頁面接收返回值它最大的鍵再存一個變數,迴圈這個變數,並且打點取數據上樹,定時器間隔請求。
概述:HTTP超文本傳輸協議,屬於短輪詢鏈接,發起一次請求與一次響應之後就斷開鏈接。
PHP session 變數用於存儲有關用戶會話的信息,或更改用戶會話的設置。Session 變數保存的信息是單一用戶的,並且可供應用程式中的所有頁面使用。
http://www.w3school.com.cn/php/php_sessions.asp
提示:session PHP有,JS也有,它是一個後臺給前端用戶發的一個‘信物’,可以分辨出誰是誰;
Session 的使用:
Session 不同於cookie,必須先啟動Session_start();
當第一次訪問網站的時候,Session_start()函數就會創建一個唯一的Session_ID。並自動通過HTTP的響應頭,將這個Session_ID保存到客戶端的coookie,同時,也在伺服器端創建了一個以Session_ID命名的文件,用於保存。
這個用戶的會話信息。當同一個用戶再次訪問這個網站的時候,也會自動的通過HTTP的請求頭將cookie中保存的session_ID再次的攜帶過來,這時,Session_start()函數就不會再次的分配一個新的Session_ID,而是在伺服器端的硬碟中去尋找個這個Session_ID同名的Session文件,將這之前的偽這個用戶保存的會話信息讀出來。在當前的腳本中應用,達到跟蹤用戶的目的。
提示:PHP中的正則方法preg_match(正則字元串,字元串)返回一個布爾值,exit是PHP中return語句。
免費API介面
https://www.zhihu.com/question/32225726
https://www.showapi.com/apiShow/apiMap
五、複習
5.1基本類型和引用類型
JavaScript語言有:語言核心、DOM、BOM,複習語言核心部分。
JavaScript的數據類型有哪些: ● 基本類型值:number、string、boolean、undefined、null ● 引用類型值:Object、Array、Function、RegExp、Math、Date
為什麼要區分基本類型和引用類型?有以下兩點不一樣:
區分的方式是根據記憶體中存儲的位置而區分。
基本類型:在記憶體中占用的空間是固定大小的,它們的值保存在棧記憶體,通過值來訪問。
引用類型:大小不固定,棧記憶體中存放它們的地址指向的是堆記憶體中的對象,是按引用訪問。
5.2棧記憶體和堆記憶體
棧(stack)會自動的分配空間,會自動的釋放空間。
堆(heap)會動態的分配記憶體空間,大小不固定,也不會自動釋放空間。
電腦中存儲的媒介:
硬碟:文檔、音樂、視頻、文檔等(電腦斷電後,數據還保留),存儲空間【240G、500G、1T、2T】
記憶體:存儲的介質,讀取和寫入速度比硬碟快(電腦斷電後數據就沒了)。存儲空間【2G、4G、8G】
CPU緩存(cache):是位於CPU與記憶體之間的臨時存儲器,電腦斷電後數據也沒了,存儲空間【256KB、2M、4M、8M】。
記憶體有五大空間:堆、棧、自由存儲空間、全局、常量
區別1:基本類型在記憶體中都是“棧記憶體”存儲,引用類型值都是“堆記憶體”存儲。
先說說什麼是記憶體?
電腦的記憶體能存多少東西?
電腦系統有位數:32位、64位
以64位舉例:記憶體條一條內容有64位的2進位的值,就是8個bytes
記憶體條4G空間等於 4 * 1024 * 1024 * 1024個bytes,也等於4 * 1024 * 1024 * 1024 ÷ 8個位元組。536870912
記憶體條8G空間等於 8 * 1024 * 1024 * 1024個bytes,也等於8 * 1024 * 1024 * 1024 ÷ 8個位元組。1073741824
記憶體中存儲的信息都有對應的地址。
基本類型值,都是記憶體中的一個小單元格中,字元串如果太長,此時會用“鏈表”的形式去規劃記憶體,此時就會認為在一個地址中。
什麼是“棧”,類似光碟架的結構、或羽毛球筒。先放進去的,一定是最後被取出來的,進出都在一端,屬於“first in last out”【FILO】
記憶體條叫做做“棧記憶體”,本質原因就是記憶體會維持一個“空白區域”的清單:
現在根據上圖,如果程式員要var a=1;此時這個1被寫入到45533地址上,因為目前它是棧頂,45533就“出棧”。
再var b=2;此時b被寫入在45534上,因為此時的棧頂是45533,就“出棧”。
此時寫var a =“哈哈”,此時a被釋放,45533重新回到棧頂,被改寫為“哈哈”的時候,此時再次出棧。等於45533的小單元格從1變為“哈哈”。
引用類型值,此時記憶體處理辦法是堆記憶體:
var arr=[1,2,3,"J","Q","小王"]; |
此時稱為堆記憶體。
區別2:基本類型在進行賦值的時候,此時會在記憶體中克隆一份;引用類型,只傳地址。
var arr=[1,2,3,"J","Q","小王"]; var b = a; |
對a的更改也會影響b。
註意:基本類型在當執行環境結束時被銷毀,而引用類型不會隨著執行環境結束而銷毀,只有當所有引用它的變數不存在時,這個對象才被垃圾回收機制回收。