出于浏览器同源政策的影响, 如果服务器不允许跨域, 客户端与服务器不同源, 请求就会失败, 提示如下
但是有些标签是例外的, 比如说图片的url, script标签的 url
而作为web脚本语言的javascript, 本质上其实是字符串
不信你可以在script内部 console.log("</script>") 试试, 这个打印会被默认成script的结束
而script请求到的内容填充到浏览器script标签后, 会立即执行里面的内容, jsonp就是利用这个机制, 让服务端返回一个函数的调用, 实现浏览器对获取的数据的处理
web代码
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>测试</title> </head><body><button>获取数据</button><ul></ul><script>const btn = document.querySelector('button')const ul = document.querySelector('ul')function render_data(data) {console.log(data)const lis = []data.forEach(d => {const li = document.createElement('li')li.textContent = d.namelis.push(li)})ul.innerHTML = ''ul.append(...lis)del_script('req1')}function del_script(id) {const script = document.querySelector(`script[data-id=${id}]`)script.remove()}btn.addEventListener('click', () => {const url = 'http://127.0.0.1:5000/get_data?cb=render_data'const script = document.createElement('script')script.setAttribute('src', url)script.setAttribute('data-id', 'req1')document.body.appendChild(script)})</script></body></html>
代码解析
点击按钮动态生成并插入script, 传入回调函数
服务器收到之后, 直接返回一个函数的调用, 参数为服务器查询到的数据(此处为模拟数据)
客户端渲染script结果后, 立即执行函数, 页面就能看到内容了
服务器代码 语言python
from flask import Flask, requestapp = Flask(__name__)@app.route('/get_data', methods=["GET"]) def get_data():cb = request.args.get('cb')lis = [{"id": 1, "name": "张三"},{"id": 2, "name": "李四"},{"id": 3, "name": "王五"},{"id": 4, "name": "赵六"},{"id": 5, "name": "小七"},]return f'{cb}({lis})'if __name__ == '__main__':app.run(debug=True)
最终可以得到页面结果
页面也无任何跨域报错