欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

浅谈javascript之JSON和跨域

程序员文章站 2022-03-11 16:04:55
目录一、JSON(1):定义一个JSON字符串(对象或数组)(2):JSON转化为js对象 ---- JSON.parse(str)(3):JSON将js对象转化为JSON字符串二、跨域同源和跨域的概念服务器的拆分跨域的详细分析解决方法一:修改浏览器的安全配置服务器代理跨域(Nginx反向代理)php的后端代理实现跨域CORS 实现跨域一、JSON1:前因 — 由于js对象只能识别js对象,java只能识别java对象,前后端数据交互,需要把数据转化为字符串,这也代表着需要一个转化工具,而这个转化工具...

一、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/index.html
    数据接口地址: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('你好啊,我不在是你了')";
?>
//结果: 你好啊,世界! 你好啊,我不在是你了

浅谈javascript之JSON和跨域

使用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