当前位置: 移动技术网 > IT编程>开发语言>JavaScript > 浅谈javascript之JSON和跨域

浅谈javascript之JSON和跨域

2020年07月14日  | 移动技术网IT编程  | 我要评论

一、JSON

1:前因 — 由于js对象只能识别js对象,java只能识别java对象,前后端数据交互,需要把数据转化为字符串,这也代表着需要一个转化工具,而这个转化工具就是JSON。
JSON就是一种特殊的字符串,这个字符串能被任意语言识别,并且能转化为任意语言的对象

2:后果 — JSON:JavaScript 对象表示法(JavaScript Object Notation)
JSON作用:主要用来数据交互中字符串和对象的互相转化
Javascript Object Notation js对象表示法
JSON和JS对象的格式一样,只不过JSON中的对象的属性名需要加""

3:JSON的分类: 对象-{} 数组-[]
4:JSON中允许的值: 1:字符串; 2:布尔值; 3:数值; 4:null; 5:数组; 6:对象;
5:JSON的转化方法
01:将JSON字符串转化为js对象的方法是 JSON.parse()
参数:为JSON字符串; 返回值:为js对
02:将js对象转化为JSON字符串的方法是 JSON.stringifg()
参数:为js对象; 返回值:为JSON字符串

(1):定义一个JSON字符串(对象或数组)

1:JSON对象 —就是字符串里面包含的是对象的格式
2:JSON数组 —就是字符串里面包含的是数组的格式

    let obj = '{"name":"pink","age":"18"}'; //创建一个JSON对象
    let arr = '[1,3,"haha"]' //创建一个JSON数组
    let obj2 = '{"arr":"[1,3,"haha","pin"]"}'
    let arr2 = '[{"name":"pink","age":"18"},{"name":"孙武汉","age":"38"}]'
    console.log(typeof obj); //string

(2):JSON转化为js对象 ---- JSON.parse(str)

    //将JSON字符串转化为对象  JSON.parse(str)
    let str = '{"name":"小李","age":13,"sex":"男"}'; //定义一个JSON字符串格式里面存放对象
    let str2 = '[{"name":"小谢","age":10,"sex":"男"},{"name":"小潘","age":16}]' //定义一个JSON字符串格式里面存放数组
    let obj = JSON.parse(str);
    console.log(typeof obj); //object
    console.log(obj); //{name: "小李", age: 13, sex: "男"}
    let arr = JSON.parse(str2);
    console.log(typeof arr); //object
    console.log(arr); //[{…}, {…}]
    console.log(arr[0]); //{name: "小谢", age: 10, sex: "男"}

(3):JSON将js对象转化为JSON字符串

    //2:将js对象转化为JSON字符串   JSON.stringifg(obj)
    let obj = {
      name: "pink",
      age: 33,
      sex: "男"
    };
    let str = JSON.stringify(obj);
    console.log(typeof str); //string
    console.log(str); //{"name":"pink","age":33,"sex":"男"}

二、跨域

同源和跨域的概念

所谓跨域就是协议号(http等)、域名(www.baidu.com等)、端口号(8080等)这三者之间出现一种不同,就是存在跨域。

  • 同源策略请求 ajax / fetch

    • 所谓同源:也就是同一个域下的两个页面的具有相同的协议,主机号(域名),端口号
    • 所谓同源策略:浏览器出于安全性问题,阻止一个域的js脚本对另外一个域的内容进行交互。
    • 跨域的原因:
      浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
      同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)
  • 跨域传输

    • 所谓跨域:就是协议,域名,端口号三者之间存在不同,就是跨域行为!

服务器的拆分

  • Web服务器:静态资源
  • data服务器:业务逻辑和数据分析
  • 图片服务器:

跨域的详细分析

  • 协议
  • 域名
  • 端口号
    假设在自己服务器上编程
    WEB服务器地址:http://127.0.01:3000/
    数据接口地址:http://127.0.01:4000/list

解决方法一:修改浏览器的安全配置

https://editor.csdn.net/md/?articleId=104475366

服务器代理跨域(Nginx反向代理)

常规的服务器有:apache和nginx等等

  • 反向代理(Reverse Proxy)

    • 是指以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器;并将从服务器上得到的结果返回给Internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。
  • 反向代理的步骤:
    01:查询配置的网站的网址和路径

    • 001:先在网站上查找你要的分类数据,点击堆糖的分类项中的美食菜谱!
    • 002:然后你选择在Network中XHR中的ajax请求:
      这边会请求到两个数据,一个是你用户的信息(user_id) 和一个美食菜谱的信息 (include_fields)
    • 003:然后点击General中的第一个Request URL 也就是请求的路径
      https://www.duitang.com/napi/blog/list/by_filter_id/? include_fields=top_comments%2Cis_root%2Csource_link%2Citem%2Cbuyable%2Croot_id%2Cstatus%2Clike_count%2Csender%2Calbum%2Creply_count&filter_id=%E7%BE%8E%E9%A3%9F%E8%8F%9C%E8%B0%B1&start=24&=1594534848872
      解析1:是资源的路径 https://www.duitang.com/napi/blog/list/by_filter_id/?
      解析2: 参数include_fields=top_comments%2Cis_root%2Csource_link%2Citem%2Cbuyable%2Croot_id%2Cstatus%2Clike_count%2Csender%2Calbum%2Creply_count&filter_id=%E7%BE%8E%E9%A3%9F%E8%8F%9C%E8%B0%B1&start=24&
      =1594534848872
    • 004:找到这些路径之后,我们可以配置nginx的代理了!

02:第一步找到nginx的配置文件! nginx.conf

  • 001: 。。。 phpstudy_pro\Extensions\Nginx1.15.11\conf\vhosts 中的localhost_80.conf文件
  • 002: 然后在内部配置需要跨域的网址:
  • 003: 以下代码解析!
    配置文件:
  //解析:localhost = 的的意思就是:地址栏上的第一个位置必须为后面书写的东西 比如(/dt) 后面为一个对象
  // 在对象里面书写的是 你要跨域访问的网站url 比如( https://www.juhe.cn/)
  // 注意点:就是/dt 也就是等于了 {里面的网址了!} 使用的时候,只需要在前面添加 /dt?拼接后面的参数!
  location = /dt {
     proxy_pass https://www.duitang.com/napi/blog/list/by_filter_id/;
   }

请求的方式的书写:

//需求:比如你想要拿到美食菜谱的img和title等等,渲染到页面,因此你可以发送一个ajax请求
//以 /dt? ---路径
    // xhr.open("GET",
    //   "/dt?include_fields=top_comments%2Cis_root%2Csource_link%2Citem%2Cbuyable%2Croot_id%2Cstatus%2Clike_count%2Csender%2Calbum%2Creply_count&filter_id=%E7%BE%8E%E9%A3%9F%E8%8F%9C%E8%B0%B1&start=24&_=1594534848872"
    // )

//详细的请求代码:

    var container = document.querySelector(".container"); //容器

    var xhr = new XMLHttpRequest()
    xhr.open("GET",
      "/dt?include_fields=top_comments%2Cis_root%2Csource_link%2Citem%2Cbuyable%2Croot_id%2Cstatus%2Clike_count%2Csender%2Calbum%2Creply_count&filter_id=%E7%BE%8E%E9%A3%9F%E8%8F%9C%E8%B0%B1&start=24&_=1594534848872"
    )
    xhr.send();

    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          // console.log(xhr.responseText); //拿到请求的数据,转为为对象的形式更方便操作! 然后拿到里面的数据,在进行循环遍历!
          var data = JSON.parse(xhr.responseText) //转化为对象的形式!
          // console.log(data);//我所要拿的数据,是data下data下的object_list 直接遍历这个对象即可!
          var data_arr = data.data.object_list; //数据
          var html = ""
          for (var i = 0; i < data_arr.length; i++) {
            // console.log(data_arr[i]);
            html += `
            <div class="box">
              <img class="img" src="${data_arr[i].photo.path}" alt="">
              <div class="title">${data_arr[i].msg}</div>
            </div>
            `
          }
          container.innerHTML = html;
        }
      }
    }

php的后端代理实现跨域

  • 需求:拿到一个天气的数据接口,渲染到页面之中!
  • 1:在php中设置
  • 2:先找到你要设置的接口php,然后复制下来!
  • 3:然后在php文件中添加以下这些!
 //一个是中文 一个是秘钥 一个是传递的参数(城市)
header('Content-type:text/html;charset=utf-8');
//配置您申请的appkey
$appkey = "04dbb4728596499a891709faed440669";
$city = $_GET["city"];

详细的php

<?php

header('Content-type:text/html;charset=utf-8');

//配置您申请的appkey
// $appkey = "04dbb4728596499a891709faed440669";
$appkey = "0cd454fbe6ac6d76c67283bb90df9837";

$city = $_GET["city"];

//************1.根据城市查询天气************
// $url = "http://v.juhe.cn/toutiao/index";
$url = "http://op.juhe.cn/onebox/weather/query";
$params = array(
     "cityname" => "$city",//要查询的城市,如:温州、上海、北京
     "key" => $appkey,//应用APPKEY(应用详细页查询)
     "type" => "json",//返回数据的格式,xml或json,默认json
);
$paramstring = http_build_query($params);
$content = juhecurl($url,$paramstring);
$result = json_decode($content,true);

if($result){
   if($result['error_code']=='0'){
       echo json_encode($result);
   }else{
       echo $result['error_code'].":".$result['reason'];
   }
}else{
   echo "请求失败";
}
//**************************************************

/**
* 请求接口返回内容
* @param  string $url [请求的URL地址]
* @param  string $params [请求的参数]
* @param  int $ipost [是否采用POST形式]
* @return  string
*/
function juhecurl($url,$params=false,$ispost=0){
   $httpInfo = array();
   $ch = curl_init();

   curl_setopt( $ch, CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_1_1 );
   curl_setopt( $ch, CURLOPT_USERAGENT , 'JuheData' );
   curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT , 60 );
   curl_setopt( $ch, CURLOPT_TIMEOUT , 60);
   curl_setopt( $ch, CURLOPT_RETURNTRANSFER , true );
   curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
   if( $ispost )
   {
       curl_setopt( $ch , CURLOPT_POST , true );
       curl_setopt( $ch , CURLOPT_POSTFIELDS , $params );
       curl_setopt( $ch , CURLOPT_URL , $url );
   }
   else
   {
       if($params){
           curl_setopt( $ch , CURLOPT_URL , $url.'?'.$params );
       }else{
           curl_setopt( $ch , CURLOPT_URL , $url);
       }
   }
   $response = curl_exec( $ch );
   if ($response === FALSE) {
       //echo "cURL Error: " . curl_error($ch);
       return false;
   }
   $httpCode = curl_getinfo( $ch , CURLINFO_HTTP_CODE );
   $httpInfo = array_merge( $httpInfo , curl_getinfo( $ch ) );
   curl_close( $ch );
   return $response;
}
?>
   * {
     margin: 0;
     padding: 0;
   }

   .container {
     margin: 0 auto;
     width: 1300px;
     min-height: 300px;
     border: 1px solid red;
     clear: both;
     overflow: hidden;
   }

   .box {
     margin: 5px;
     float: left;
     width: 250px;
     height: 400px;
     border: 1px solid #ccc;
   }

   .box:last-child {
     margin-right: 0;
   }

   .city_code {
     height: 30px;
     line-height: 30px;
     background: pink;
     color: #fff;
   }

   .city_name {
     height: 16px;
     line-height: 16px;
     color: #ccc;
   }

   .date {
     height: 20px;
     line-height: 20px;
   }

   .moon {
     height: 20px;
     line-height: 20px;
   }

   .box img {
     display: block;
     width: 200px;
     height: 200px;
   }

   .time {
     height: 20px;
     line-height: 20px;
   }

   #list li {
     margin-top: 5px;
     height: 20px;
     line-height: 20px;
     background: yellow;
   }
 <div class="container">
   <!-- <div class="box">
     <div class="city_code"></div>
     <div class="city_name"></div>
     <div class="date"></div>
     <div class="moon"></div>
     <div class="time"></div>
     <ul id="list">
       <li></li>
     </ul>
   </div> -->
 </div>

   var container = document.querySelector(".container")

   //需求:使用后端php代理的方式,去访问外部接口,拿到城市的头条新闻!
   // var city = prompt("请输入你需要得到天气的城市:");
   var xhr = new XMLHttpRequest();
   xhr.open("GET", "./02.php?city=" + "北京")
   xhr.send()

   xhr.onreadystatechange = function () {
     if (xhr.readyState === 4) {
       if (xhr.status === 200) {
         var data = JSON.parse(xhr.responseText);
         // console.log(data); //result - data 
         var data_arr = data.result.data.realtime;
         // console.log(data_arr); //遍历对象
         var html = ""
         var obj = data_arr["weather"]
         var arr = [] //定义一个空数组
         for (var key in obj) {
           arr.push(obj[key])
         }
         for (var key in data_arr) {
           html = `
           <div class="box">
             <div class="city_code">${data_arr["city_code"]}</div>
             <div class="city_name">${data_arr["city_name"]}</div>
             <div class="date">${data_arr["date"]}</div>
             <div class="moon">${data_arr["moon"]}</div>
             <div class="time">${data_arr["time"]}</div>
             <ul id="list">
               ${ arr.map(function(item,i){
                 return `<li>${item}</li>
                 `
               }).join("") }

             </ul>
           </div>
         `
         }
         container.innerHTML = html;
       }
     }
   }

CORS 实现跨域

  • 跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。
  • 操作:在后端php语言中添加一个响应头, header(“Access-Control-Allow-Origin:链接”);
  • 这样使得链接能够实现跨域访问!
  • 需求:
    • 1:就是你发起请求的路径的为 http://127.0.0.1/0710/跨域/03.cors.php
    • 2:然后你在浏览器输入的路径为localhost/0710/跨域/03.cors.php 这样的话会导致跨域问题!
    • 3:解决方案:就是在后端的php之中,添加一个CORS跨域资源共享即可!
      header(“Access-Control-Allow-Origin:http://localhost”);
      这一句话的意思就是:可以接受请求的资源中域名为localhost的!
      注意点:若是不添加以上的请求头,可接受请求域名为localhost的!会造成以下的错误!
      Access to XMLHttpRequest at ‘http://127.0.0.1/0710/。。。。。’ from origin ‘http://localhost’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
  • 以下为解决方案:
<?php
      header("Access-Control-Allow-Origin:http://localhost");
      echo "hello world";
?>
    var xhr = new XMLHttpRequest()
    xhr.open("GET", "http://127.0.0.1/0710/跨域/03.cors.php")
    xhr.send()

    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          console.log(xhr.responseText);
          //然后利用这个数据 遍历渲染!
        }
      }
    }

jsonp 实现跨域

  • jsonp:所谓的jsonp就是包裹着json数据! 而jsonp跨域就是把json数据存放在一个回调函数里面,用src发起http请求,来获取数据,来实现跨域!
    当xhr被禁止的时候,那么可以使用jsonp来实现跨域的行为!
  • 原理:就是使用标签中的src开发策略,来发起http请求,
    • 01:img中src可以发送一个http请求,只不过还会把这个请求的数据解析为img所能识别的,不方便操作,因此不适应!
    • 02:script标签中的src发起一个http请求,这样拿到数据之后,可以存放在一个回调函数里面
      • 注意点1:回调函数的作用:就是外部数据,可以通过调用的时候,传入参数来访问内部数据!
      • 注意点2:拿到的数据的时候,需要设置为全局变量,这样才能实现共享!
  • 方案:
    • 01:前端定义一个全局函数
    • 02:前端中,script标签中的src发起一个http请求(跨域请求,请求其他的js文件,来获取到数据!)
    • 03:请求的内容调用前端函数(可以在其他的js文件中调用,也可以在后端php等调用)
    • 04:调用时传入实参,在前端全局函数使用形参接受;(其他的文件中的js或者后端传入参数)

一个简单的jsonp跨域!

  • 需求:在前端之中,定义一个全局函数,然后在外部或者后端使用这个回调函数
  • 访问的时候:http://localhost/0711/01jsonp.html
//HTML
  <script>
    function callback(data) {
      console.log(data);
    }
  </script>
  <script src="http://127.0.0.1/0711/01jsonp.js"></script>
  <script src="http://127.0.0.1/0711/01jsonp.php"></script>
//JS
callback("你好啊,世界!");

//PHP
<?php 

  echo "callback('你好啊,我不在是你了')";
?>
//结果: 你好啊,世界! 你好啊,我不在是你了

在这里插入图片描述

使用jsonp跨域的方式,来实现仿百度的搜索框!

//HTML
  <p>
    <input autofocus type="text" id="ipt">
    <button id="seqrch">搜索</button>
    <ul class="list">
      <!-- <li><a href=""></a></li> -->
    </ul>
  </p>
//CSS
    * {
      margin: 0;
      padding: 0;
    }

    li,
    ul {
      list-style: none;
    }

    p {
      position: relative;
      margin: 30px;
      height: 30px;
      line-height: 30px;
    }

    p input {
      border: 0;
      height: 30px;
      line-height: 30px;
      width: 200px;
      background: yellow;
    }

    .list {
      display: none;
      position: absolute;
      top: 62px;
      left: 30px;
      width: 200px;
      min-height: 30px;
      overflow: hidden;
      background: #fff;
      background: red;
    }
//JS
 var ipt = document.querySelector("#ipt") //表单
    var btn = document.querySelector(".search") //按钮
    var list = document.querySelector(".list"); //列表
    //点击搜索按钮
    ipt.oninput = function (e) {
      iptVal = ipt.value; //拿到表单的值 
      //发起请求
      ajax({
        method: "jsonp",
        url: "https://www.baidu.com/sugrec",
        data: {
          pre: 1,
          p: 3,
          ie: "utf-8",
          json: 1,
          prod: "pc",
          from: "pc_web",
          sugsid: "32218,1425,31672,32139,31254,32045,32230,32299,31639",
          //这是你表单输入的时候,拿到的值,去数据库查询!
          wd: iptVal,
          req: 2,
          csor: 5,
          cb: "callback",
          _: Date.now()
        },
        jsonpcallback: "callback",
        callback: function (data) {
          list.style.display = "block"
          var arr = data.g //拿到数据 数组的形式
          if (arr instanceof Array) {
            list.innerHTML = arr.map(function (item, i) {
              // console.log(item.q);
              return `
            <li><a href="">${item.q}</a></li>
            `
            }).join("")
          } else {
            list.style.display = "none"
          }
        }
      })
    }
    document.onclick = function () {
      list.style.display = "none"
    }

本文地址:https://blog.csdn.net/weixin_43845137/article/details/107305924

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网