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


      最近在做微信公众号的微网页,有两个方案,一是使用原来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,还有一些参数,然后直接写个回调函数,就可以拉。

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

  • 相关阅读:
    数据库----索引与补充
    数据库----知识点总结
    数据库----mysql 存储引擎,表介绍
    数据库----mysql表的约束和查询
    数据库----mysql 表的操作
    初识数据库
    并发编程----协程
    并发编程----同步,异步,阻塞,非阻塞,异步加回调机制,线程队列,event事件
    并发编程----GIL,进程池/线程池
    django中的模板渲染、模板继承、组件、插件
  • 原文地址:https://www.cnblogs.com/fengru/p/6868818.html
Copyright © 2020-2023  润新知