同源策略html
若是兩個頁面的協議,端口(若是有指定)和域名都相同,則兩個頁面具備相同的源。ajax
示例:兩個Django demojson
demo1後端
url.py跨域
url(r'^demo1/',demo1),
view.py瀏覽器
def demo1(request): return HttpResponse("demo1")
demo2app
url.pyide
url(r'demo2$',demo2),
view.py函數
def demo2(request): return render(request,'demo.html')
demo.htmljsonp
<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>
啓動瀏覽器,訪問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>
刷新瀏覽器
說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>
而後不報錯了。
那在定義一個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>
修改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>
修改demo1的view.py
import json def demo1(request): ret = {"status": 1, "msg": "demo1"} return HttpResponse("demo1({})".format(json.dumps(ret)))
刷新瀏覽器看效果。
這其實就是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>
此時經過按鈕就能夠動態的在頁面上插入一個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>
修改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)))
此時實現動態的調用了。
然而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>
注意的是在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>