一、請求後端的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。
注意:基本型別在當執行環境結束時被銷燬,而引用型別不會隨著執行環境結束而銷燬,只有當所有引用它的變數不存在時,這個物件才被垃圾回收機制回收。