前后端交互 -跨域问题

ajax如何跨域

  • 同源策略是指 协议、域名,端口号 都一致 这是浏览器的强制规定

ajax 能不能跨域

  • 测试 ajax 能不能实现跨域(准备两个后端) 为了测试方便所有的页面都直接放在了 static 文件夹下

后端服务器的准备

  1. 负责准备数据的后端
const Koa = require("koa");
	const Router = require("koa-router");
	const static = require("koa-static");
	const koaBody = require("koa-body");
	
	let app = new Koa();
	let  router = new Router();
	app.use(koaBody({
	    multipart : true
	}));
	app.use(static(__dirname+"/static"));
	
	router.get("/",async ctx =>{
		// 测试数据,查看路由是否加载成功
	    ctx.body = {
	        name:"Mr_Qin",
	        age:"24"
	    };
	    // ctx.render()
	}); 
	
	router.get("/getAjax",async ctx =>{
	    console.log("来自 4000 的数据");	    
	    // 服务端没有返回任何东西的话 也会报错
	    ctx.body = " var a = 24 ";
	})
	
	app.use(router.routes());
	app.listen(4000);
  1. 启动服务的后端
const Koa = require("koa");
	const Router = require("koa-router");
	const static = require("koa-static");
	const koaBody = require("koa-body");
	
	let app = new Koa();
	let  router = new Router();
	app.use(koaBody({
	    multipart : true
	}));
	
	app.use(static(__dirname+"/static"));
	
	router.get("/",async ctx =>{
	    ctx.body = {
	        name:"Mr_Qin",
	        age:"24"
	    };
	    // ctx.render()
	}); 
	
	app.use(router.routes());
	app.listen(3000);

前端页面的准备

  • 两个终端都要运行,启动服务 尝试跨域时,
  • ajax 下的 open 方法的第二个值设置为 跨域的路由
<button>获取ajax</button>


<script>
        // ajax 不能实现跨域 自身无法做到
        document.querySelector("button").onclick = function(){            
            let xhr = new XMLHttpRequest();            
            // 尝试 ajax 直接跨域       
            xhr.open("get","http://localhost:4000/getAjax",true);
            xhr.onload = function(){
                console.log(xhr.responseText)
            }
            xhr.send()
        }               
    </script>

jsonp 方式跨域

  • 根本原理
  • 利用 script / img 标签 可以直接跨域访问的标签的特性( 浏览器不会限制这两个标签 )

可以跨域的标签(测试)

  • 前端页面准备
<!-- 引入网络链接 script 跨域访问可实现 -->
	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	<!-- 引入网络链接 img 跨域访问可实现 -->
	<img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1586328014788&di=def29a76ad69feeba01313fe559644d0&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20190121%2Fc884227770e64b67b024d48a8b51daca.jpeg" alt="" >
	<!-- 注意参数的写法 字符串需要加符号 数字不需要 -->
    <script src="http://localhost:4000/getAjax"></script>
    <!-- jsonp 雏形 -->
    <script>
        // 输出引入的 vue
        console.log(Vue);
        console.log(a);
    </script>
  • 后端服务器准备( 端口号为4000的服务器 )
router.get("/getAjax",async ctx =>{
	    console.log("来自 4000 的数据");
	    // 服务端没有返回任何东西的话 也会报错
	    ctx.body = " var a = 24 ";
	})

(直接返回JS代码)存在小问题

  • 通常情况下后端返回的数据会很杂,一系列的功能代码 不可能像测试时的 ctx.body = "var a = 24 ",这么简单
    那这样复杂的情况就明显不符合需求

前端页面处理

document.querySelector("button").onclick = function(){
	let port = 4000; // 这里需要 前、后端 协调处理
	let o = document.createElement("script");
	o.src = `http://localhost:${port}/getAjax`; 
	document.querySelector("head").appendChild(o);
	// console.log(a) // 报错不会发现,原因:同步的问题直接加载过了
	// 不会很推荐  解决方式存在一些问题 小功能可以使用
	o.onload = function(){
		console.log(a);
	}
}

优化处理

处理方式,前端写函数传递到后端,再由后端将函数携带参数后返回

  • 前端页面处理
	<button>点击获取跨域资源</button>
	
    <script>     
        function cbfn(res){
        	//  后端返回的数据在这里
            console.log(res);
        }
        document.querySelector("button").onclick = function(){
            let port = 4000; // 这里需要 前、后端 协调处理
            let o = document.createElement("script");
            // 属性名 叫 cb 还是 callback 需要和后端 沟通过好 双方一致
            o.src = `http://localhost:${port}/getAjax?cb=cbfn`; 
            // cb 传递的是一个函数体 给后端
            document.querySelector("head").appendChild(o);
        }

    </script>
  • 后端服务器处理
router.get("/getAjax",async ctx =>{
    let obj = {
        aname:"卡特琳娜",
        sex:"女"
    }
    // 这里的 cb 是和后端人员共同拟定的名字
    let cb = ctx.query.cb; // 来自前端的 ?cb=cbfn 
    // 封装的方法时 传入的参数为同样为 cb
    console.log(cb);
    // 将参数传递回前端
    ctx.body = `${cb}(${JSON.stringify(obj)})`;
})

ajax 实现 jsonp

后端数据准备的服务器不需要变
前端需要引入封装好的 jsonp.js 文件(这里省略了)

<button>请求jsonp</button>
    <!-- 引入封装的方法 -->
    <script src="jsonp.js"></script>
    <script>
        //  回调函数 负责 去后端接收数据 并返回
        function cbFn(res){
            console.log(res)
        }
        // 封装的功能中 存在 ajax
        document.querySelector("button").onclick = function(){
            // 和 jQuery 很像
            ajax({
                url:"http://localhost:4000/getAjax",
                data:{
                    name:"Mr_Qin",
                    age:"25"
                },
                dataType:"jsonp",
                jsonp:"cbFn",// 回调函数 => 后端修改为 ctx.query.cbFn
                success:function(res){ // 成功后返回的数据 
                    console.log(res);
                }
            })
        }
	</script>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值