• 微网页关于跨域的一些相关问题


      最近在做微信公众号的微网页,有两个方案,一是使用原来web端的内容,直接改页面,改成手机端的样子,然后把一些多余的东西去掉,这样的话页面也需要改动,后台也需要改动。

    二是直接用app的接口,因为页面设计的其实和app差不多,用到的数据基本都一样,这样的话可以不用写后台的接口了,只需要做页面,然后调接口,显示数据就可以了。

      然而遇到了第一个问题就是,普通的ajax请求无法使用,原因是跨域了。具体跨域就不多说了,一般跨域都是使用jsonp来调接口。

      然而。。。jsonp只能使用GET方式,而且我们的app的接口传回的数据是压缩的json。不是直接可以用的json,无法解压。

      后来。。。考虑到正好页面是用H5做的,就用H5的跨域来解决吧~

    H5的跨域说起来很简单,无非就是:

    1.页面和其打开的新窗口的数据传递

    2.多窗口之间消息传递

    3.页面与嵌套的iframe消息传递

    4.上面三个问题的跨域数据传递

    postMessage()

    这些问题都有一些解决办法,但html5引入的message的API可以更方便、有效、安全的解决这些难题。postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。

    postMessage(data,origin)方法接受两个参数

     1.data:要传递的数据,html5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象,然而并不是所有浏览器都做到了这点儿,部分浏览器只能处理字符串参数,所以我们在传递参数的时候需要使用JSON.stringify()方法对对象参数序列化,在低版本IE中引用json2.js可以实现类似效果。

    2.origin:字符串参数,指明目标窗口的源,协议+主机+端口号[+URL],URL会被忽略,所以可以不写,这个参数是为了安全考虑,postMessage()方法只会将message传递给指定窗口,当然如果愿意也可以建参数设置为"*",这样可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。

    具体我们是如何操作的呢?

    首先页面上需要引入iframe:

    <iframe id="child" src="http://m.nbcyl.com/resources/app/resultData.html"  width="0" height="0"></iframe>
    

    这个html里面有什么呢?

    <!doctype html>
     <html>
         <head>
             
         </head>
         <body >
             
    		 <script type="text/javascript" src="http://m.nbcyl.com/resources/admin/js/jquery.js"></script>
             <script type="text/javascript">
    		 
    		 function getData(data) {
    
    				var array = new Array();
    				var json = JSON.parse(data);
    				array[0]=json.url;
    				var oReq = new XMLHttpRequest();
    				var params ='';
    				if (json.type == 'GET') {
    					params = '?' + json.params;
    				} else if (json.type == 'POST'){
    					params = json.params;
    				}
    				oReq.open(json.type, json.url + params, true);
    				oReq.responseType = "arraybuffer";
    				oReq.onreadystatechange=function()
    				{
    					if (oReq.readyState==4 && oReq.status==200)
    					{
    						 var arrayBuffer = oReq.response; // Note: not oReq.responseText
    						  if (arrayBuffer) {
    							var byteArray = new Uint8Array(arrayBuffer);
    							
    							array[1]=arrayBuffer;
    							
    							window.parent.postMessage(array,'*');
    						  }
    					}
    				}
    				
    				if (json.type == 'GET') {
    					params = null;
    				}
    			oReq.send(params);
    		 }
    		 //getData();
                 var container=document.getElementById('container');
     
                 window.addEventListener('message',function(e){
    				var data = e.data;
                    if(e.source!=window.parent) 
    				return;
    				 getData(data);
                 },false);
     
                 
             </script>
         </body>
     </html>
    

      简单说一下过程,其实就是在页面上发送postMessage方法,到iframe页面里,这个页面是在那个跨域的URL服务器里的,然后 到了这个HTML里,有一个监听方法,来获取发送的数据,然后在此发送给具体的接口,并返回数据。

    我们是提取了一个公共的js:

    var waterfall = {
    
    		pageSize:3,
    		pageNumber:1,
    		ajaxType: "GET",
    		url: "",
    		urls:new Array(),
    
    		/**
    		 * 多个调用跨域链接 根据url
    		 * @param url
    		 * 			后台接口地址
    		 * @param arrayFilters
    		 * 			接口参数params
    		 */
    
    		setWaterFalls:function (url,arrayFilters,success) {
    
    			//var url = waterfall.urls;			
    			var type = waterfall.type;
    			var template = waterfall.template;
    			var pageNumber = waterfall.pageNumber;
    
    			// 拼接参数(旧格式key:value,key:value)
    			//var params ={pageNumber: pageNumber, pageSize: waterfall.pageSize};
    			// if (arrayFilters != null && arrayFilters != "") {
    			// 	var filters = arrayFilters.split("&");
    			// 		for (var x = 0; x < filters.length; x++) {
    			// 			var filter = filters[x].split("=");
    			// 			params[filter[0]]=filter[1];
    			// 		}
    			// }
    			
    			// 拼接参数(新格式key=value&key=value)
    			var params = 'pageNumber='+pageNumber+'&pageSize='+waterfall.pageSize;
    			params+='&'+arrayFilters;
    			waterfall.getWaterFalls(url,type,params,success);
    					
    		},
    
    		/**
    		 * 调多个接口 发送链接 跨域
    		 * @param url
    		 * 			后台地址
    		 * @param type
    		 *          请求类型
    		 * @param params
    		 * 			参数条件 json:{pageNumber=1, pageSize=pageSize, Id=100}
    		 * @param success
    		 * 			成功回调函数
    		 */
    		getWaterFalls : function (url,type,params,success) {
    //			$.ajax({
    //			 	url:url,
    //			 	type: type,
    // 	 			data: params,
    // 				jsonpCallback:"success_jsonpCallback",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名
    // 				dataType: "jsonp",
    // 				success:function(data){
    // 					success(data);
    // 				}
    // 			});		
    			var message = JSON.stringify({url:url,type:type,params:params});
    			//发送跨域页面传递消息 页面在发送请求
                window.frames[0].postMessage(message,'http://m.nbcyl.com');
    	        //监听回调 解压数据
    	        window.addEventListener('message',function(e){ 
    				if (e.returnValue) {
    					e.returnValue=false;
    					var url = e.data[0];
    					str = pako.ungzip( e.data[1], { to: 'string' } );
    					var result  = JSON.parse(str);				
    					success(url,result);
    				}
    	        },false);
    		
    		},
    	
    		/**
    		 * 单个调用跨域链接 根据url
    		 * @param url
    		 * 			后台接口地址
    		 * @param arrayFilters
    		 * 			接口参数params
    		 */
    
    		setWaterFall:function (arrayFilters,success) {
    
    			var url = waterfall.url;			
    			var type = waterfall.type;
    			var template = waterfall.template;
    			var pageNumber = waterfall.pageNumber;
    
    			// 拼接参数(新格式key=value&key=value)
    			var params = 'pageNumber='+pageNumber+'&pageSize='+waterfall.pageSize;
    			params+='&'+arrayFilters;
    			waterfall.getWaterFall(url,type,params,success);
    					
    		},
    		/**
    		 * 调单个接口 发送链接 跨域
    		 * @param url
    		 * 			后台地址
    		 * @param type
    		 *          类型
    		 * @param params
    		 * 			参数条件 json:{pageNumber=1, pageSize=pageSize, categoryId=100}
    		 * @param success
    		 * 			成功回调函数
    		 */
    		getWaterFall : function (url,type,params,success) {
    
    			var message = JSON.stringify({url:url,type:type,params:params});
                 window.frames[0].postMessage(message,'http://m.nbcyl.com');
    	        //发送请求 并解压数据
    	         window.addEventListener('message',function(e){ 
    				if (e.returnValue) {
    					e.returnValue=false;
    					str = pako.ungzip( e.data[1], { to: 'string' } );
    					var result  = JSON.parse(str);
    					success(result);
    					
    				}
    	         },false);
    		
    		},
    
    };
    

      具体在页面上使用就可以直接这样:

    //列表参数
    var params = "orderType=dateDesc";
    
    window.onload=function(){
        //最新推荐
        waterfall.url="http://m.nbcyl.com/app/integration/search.jhtml";
        waterfall.type="GET";
        waterfall.pageNumber=1;
        waterfall.pageSize=8;
        waterfall.setWaterFall(params,success);
    
        //回调函数
        function success(message) {  
                
        }   
    }    
    

      设置一下url,type,还有一些参数,然后直接写个回调函数,就可以拉。

    就想到了这么多,还有多个接口调用的,具体就不写了。。。。。。下班

  • 相关阅读:
    我爱java系列之---【微服务间的认证—Feign拦截器】
    我爱java系列之---【设置权限的三种解决方案】
    581. Shortest Unsorted Continuous Subarray
    129. Sum Root to Leaf Numbers
    513. Find Bottom Left Tree Value
    515. Find Largest Value in Each Tree Row
    155. Min Stack max stack Maxpop O(1) 操作
    painting house
    Minimum Adjustment Cost
    k Sum
  • 原文地址:https://www.cnblogs.com/fengru/p/6868818.html
Copyright © 2020-2023  润新知