同源策略 如果兩個頁面的協議,埠(如果有指定)和功能變數名稱都相同,則兩個頁面具有相同的源。 示例:兩個Django demo demo1 url.py view.py demo2 url.py view.py demo.html <body> <button id="btn">點擊</button> < ...
同源策略
如果兩個頁面的協議,埠(如果有指定)和功能變數名稱都相同,則兩個頁面具有相同的源。
示例:兩個Django demo
demo1
url.py
url(r'^demo1/',demo1),
view.py
def demo1(request): return HttpResponse("demo1")
demo2
url.py
url(r'demo2$',demo2),
view.py
def demo2(request): return render(request,'demo.html')
demo.html
<body> <button id="btn">點擊</button> <script> $("#btn").click(function () { $.ajax({ url:"http://127.0.0.1:8002/demo1/", type:"get", }).done(function (data) { console.log(data) }) }); </script> </body>View Code
啟動瀏覽器,訪問http://127.0.0.1:8001/demo2,點擊按鈕,然後控制台報錯
為什麼報錯?因為同源策略限制跨域發送ajax請求。
我們用script標簽引入cdn沒有報錯,so,用script解決問題試試。
修改demo.html
<body> <button id="btn">點擊</button> <script src="http://127.0.0.1:8002/demo1"></script> </body>View Code
刷新瀏覽器
說demo1未定義,那定義一個demo1;修改demo.html
<body> <button id="btn">點擊</button> <script> var demo1 = "demo1" </script> <script src="http://127.0.0.1:8002/demo1/"></script> </script> </body>View Code
然後不報錯了。
那在定義一個demo1函數,看看效果;修改demo.html
<body> <button id="btn">點擊</button> <script> function demo1(){ console.log("demo1") } </script> <script src="http://127.0.0.1:8002/demo1/"></script> </body>View Code
修改demo1的view.py
def demo1(request): return HttpResponse("demo1()")
nice,已經能執行函數了。那給函數加參數看看效果。
修改demo.html
<body> <button id="btn">點擊</button> <script> function demo1(ret){ console.log(ret) } </script> <script src="http://127.0.0.1:8002/demo1/"></script> </body>View Code
修改demo1的view.py
import json def demo1(request): ret = {"status": 1, "msg": "demo1"} return HttpResponse("demo1({})".format(json.dumps(ret)))View Code
刷新瀏覽器看效果。
這其實就是JSONP的簡單實現模式,或者說是JSONP的原型:創建一個回調函數,然後在遠程服務上調用這個函數並且將JSON 數據形式作為參數傳遞,完成回調。
將JSON數據填充進回調函數,這就是JSONP的JSON+Padding的含義。
通過js動態的創建script標簽來實現數據的獲取。
修改demo.html
<body> <button id="btn">點擊</button> <script> function demo1(ret){ console.log(ret) } function addScriptTag(src) { var sTag = document.createElement("script"); $(sTag).attr("src", src); $("body").append(sTag); $(sTag).remove(); } </script> <script> $("#btn").click(function () { addScriptTag("http://127.0.0.1:8002/demo1/") }) </script> </body>View Code
此時通過按鈕就可以動態的在頁面上插入一個script標簽,然後從後端獲取數據。
為了實現更加靈活的調用,我們可以把客戶端定義的回調函數的函數名傳給服務端,服務端則會返回以該回調函數名,將獲取的json數據傳入這個函數完成回調。
修改demo.html
<body> <button id="btn">點擊</button> <script> function demo1(ret){ console.log(ret) } function addScriptTag(src) { var sTag = document.createElement("script"); $(sTag).attr("src", src); $("body").append(sTag); $(sTag).remove(); } </script> <script> $("#btn").click(function () { addScriptTag("http://127.0.0.1:8002/demo1/?callback=demo1") }) </script> </body>View Code
修改demo1中的views.py
import json def demo1(request): ret = {"status": 1, "msg": "demo1"} func_name = request.GET.get("callback") return HttpResponse("{}({})".format(func_name, json.dumps(ret)))View Code
此時實現動態的調用了。
然而jQuery中有專門的方法實現jsonp。
修改demo.html
<body> <button id="btn">點擊</button> <script> $("#btn").click(function () { $.getJSON("http://127.0.0.1:8002/demo1/?callback=?",function (data) { console.log(data) }) }) </script>View Code
註意的是在url的後面必須要有一個callback參數,這樣getJSON方法才會知道是用JSONP方式去訪問服務,callback後面的那個?是jQuery內部自動生成的一個回調函數名。
但是如果我們想自己指定回調函數名,或者說服務上規定了回調函數名該怎麼辦呢?我們可以使用$.ajax方法來實現:
修改demo.html
<body> <button id="btn">點擊</button> <script> $("#btn").click(function () { $.ajax({ url:"http://127.0.0.1:8002/demo1/", dataType:"jsonp", jsonp:"callback", jsonpCallback:"demo1" }).done(function (data) { console.log(data) }) }); </script> </body>View Code