JS之ajax跨域

1、跨域

概念:网站A去访问网站B的数据。

Ajax跨域的存在的问题:浏览器的同源策略,该策略会阻止ajax跨域访问。

同源策略(Same origin policy):它是由Netscape提出的一个著名的安全策略。

所谓同源是指,域名,协议,端口相同。

如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。

如下:

2、解决跨域的三种方式

2.1、服务器代理

核心思想:php中哟一个函数 file_get_contents。该函数能够获取其他网站的数据。

www.hf.cn服务器a.html文件希望获取www.study.com服务器data.php文件返回的数据,但是由于同源的策略的限制,不能直接获取。

扫描二维码关注公众号,回复: 2313379 查看本文章

a.html文件通过ajax请求本服务器中的proxy.php文件,该文件中使用file_get_contents函数将data.php的数据获取到,然后在返回给a.html

的ajax请求。

代码实现:

a.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
  <title>Document</title>
  <script src="./jquery-1.12.4.js"></script>
</head>
<body>
  123
  <script type="text/javascript">
    $.get('proxy.php','get',function(msg){
      console.log(msg);
    },'json');
  </script>
</body>
</html>

proxy.php

<?php
echo file_get_contents('http://www.study.com/data.php');
?>

data.php

<?php
echo "321";
?>

2.2、cors跨域——跨域资源共享

同源策略是浏览器的策略。但是如果服务器允许其他网站的页面进行跨域访问,那么浏览器就不会对返回的数据进行限制了。

核心方法: 在服务器端(PHP文件中)声明不用进行同源限制

如果设置为 * 则是所有外部网站都可以获取数据:header('Access-Control-Allow-origin: *');

只允许www.hf.cn网站访问并获取数据:header('Access-Control-Allow-origin: http://www.hf.cn');

代码实现:

a.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
  <title>Document</title>
  <script src="./jquery-1.12.4.js"></script>
</head>
<body>
  <script type="text/javascript">
    $.get('http://www.study.cn/data.php','get',function(msg){
      console.log(msg);
    },'json');
  </script>
</body>
</html>

data.php

<?php
header('Access-Control-Allow-origin: http://www.study.com'); 
echo "321";
?>

2.3、jsonp跨域

JSONP(JSON with Padding) : 是一种解决ajax跨域访问的方案。

核心思想: 浏览器虽然有同源策略,但是 src 和 href 两个属性却可以跨域访问。 可以利用这一“漏洞”发送ajax请求。

本地简单案例一:

www.hf.cn的a.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
    <script type="text/javascript" src="http://www.study.com/data.php"></script>
</body>
</html>

www.study.com/data.php:

<?php
echo "console.log('123')";
?>

注意:如果data.php文件echo ‘a’;这时会在a.html文件提示错误, 'a' is not define

说明:a在a.html被解析成一个函数,在data.php中,请求结果被作为函数调用了

如果在前端页面定义好函数a

本地案例二:

www.hf.cn的a.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <script>
    function a() {
      console.log('被调用了');
    }
  </script>
  <script type="text/javascript" src="http://www.study.com/data.php"></script>
</body>
</html>

www.study.com/data.php:

<?php
echo 'a()';
?>

$.ajax方法跨域操作 --- jsonp方式

$.post $.get $.ajax都能发送跨域请求。但是,$.post和$.get是要依靠cors方式的,只有$.ajax能使用jsonp方式。

核心:

  • ​ 必须设置请求类型为get --- type: ‘get’

  • ​ 必须设置dataType为jsonp --- dataType: ‘jsonp’

  • ​ 必须额外设置一个jsonp参数,该参数值可以是任何英文字符串,常用callback。该函数的作用是在前端自动创建一个以该字符串为名称的函数名

本地案例:

www.hf.cn的a.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
  <title>Document</title>
  <script src="./jquery-1.12.4.js"></script>
</head>
<body>
  <script>
    $.ajax({
        url: 'http://www.study.com/data.php',
        type: 'get',   
        dataType: 'jsonp',   
        jsonp: 'callback',  //解决前后端函数名统一的问题   
        success: function(msg){
            console.log(msg);
        }
    })
  </script>
</body>
</html>

www.study.com/data.php:

<?php 
// 函数名
$callback = $_GET['callback'];
// 把字符串作为函数的实参
$str = '{"a":"hello","b":"world"}';
echo $callback . "('$str')";
?>

效果:

某宝跨域案例(仅用于学习)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="./index.css">
  <script src="./jquery-1.12.4.js"></script>
  <script src="./artTemplate/template-web.js"></script>
  <title>某宝跨域案例</title>
</head>
<body>
  <div class="box">
      <input type="search" id="search" data-searchBox="search">
      <div id="list">
         
      </div>
  </div>
  <script type="text/template" id="tpl">
    <ul>
      <% for(var i = 0; i < result.length; i++) { %>
        <li><%=result[i][0]%></li>
      <% } %>
    </ul>
  </script>

  <script>
    $('#search').on('input',function(){
      var value = $(this).val();
      $.ajax({
        /* 网页提供 */
        url:'https://suggest.taobao.com/sug?code=utf-8',
        data: {q:value},
        type:'get',
        dataType: 'jsonp',
        jsonp: 'callback',
        success: function(data) {
          console.log(data.result);
          $('#list').append(template('tpl',data));
        }
      })
    })
  </script>
</body>
</html>

显示效果:

某搜索跨域案例

利用src属性实现跨域请求:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    body,ul,li {
      margin: 0;
      padding: 0;
      list-style: none;
    }
    .main {
      width: 541px;
      height: 46px;
      margin: 100px auto;
      position: relative;
    }
    .main .search {
      width: 100%;
      height: 100%;
    }
    .main  #searchBox {
      display: block;
      width: 100%;
      height: 100%;
      padding: 5px 10px 5px 10px;
      border: 1px solid #19b955;
      box-sizing: border-box;
    }
    .main #btn {
      position: absolute;
      display: block;
      right: 0;
      top: 0;
      width: 20%;
      height: 100%;
      line-height: 100%;
      background: #19b955;
      font: 400 18px Arial;
      color: #fff;
      text-align: center;
      border: none;
      outline: none;
    }
    .show {
      width: 80%;
      border: 1px solid #ccc;
    }
    .show ul {
      width: 100%;
      height: 100%;
    }
    .show ul li {
      width: 100%;
      height: 20px;
      padding-top: 5px;
      padding-bottom: 5px;
      text-align:left;
      text-indent:10px;
      cursor:pointer;
    }
  </style>
  <script src="./libs/jquery.min.js"></script>
</head>
<body>
  <div class="main">
      <div class="search">
        <input type="text" id="searchBox">
      </div>
      <input type="button" value="搜 索" id="btn">
      <div class="show" style="display: none;">
        <ul>    </ul>
      </div>
  </div>
  
  <script>
    /* 3.增加鼠标移入样式,浏览器渲染完毕,li是keyup事件结束以后追加到html上的,如果
    直接给li绑定事件,是获取不到元素的,这时我们需要事件委托 */
    $(".show>ul").on("mouseover","li",function () {
        this.style.background = "#efefef";
    });
    $(".show>ul").on("mouseout","li",function () {
        this.style.background = "white";
    });

    /* 2.创建搜索引擎返回来数据的回调函数,解析数据 */
    function suggest_so(data) {
      var results = data.result;
      console.log(results);
      var ul = document.getElementsByTagName("ul")[0];
      ul.innerHTML = "";
      for (var i = 0; i < results.length; i++) {
        var li = document.createElement("li");
        li.innerHTML = results[i].word;
        ul.appendChild(li);
      }
    }

    /* 1.添加键盘事件,获取输入的值 */
    document.getElementById('searchBox').onkeyup = function () {
      var keyword = this.value;
      /* 去掉数据开始和结束的空格 */
      value = keyword.trim();
      if(value.length > 0) {
        /* 显示隐藏的div */
        document.getElementsByClassName('show')[0].style.display = 'block';
        /* 利用 src 跨域访问 */
        var tag = document.createElement("script");
        tag.src = "https://sug.so.360.cn/suggest?callback=suggest_so&encodein=utf-8&encodeout=utf-8&format=json&fields=word&word=a" + value;
        /* 将这个script标签添加到html结构中 */
        document.body.appendChild(tag);
      } else {
        document.getElementsByClassName('show')[0].style.display = 'none';
      }
    }
  </script>
</body>
</html>

效果:

利用ajax实现跨域:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    body,ul,li {
      margin: 0;
      padding: 0;
      list-style: none;
    }
    .main {
      width: 541px;
      height: 46px;
      margin: 100px auto;
      position: relative;
    }
    .main .search {
      width: 100%;
      height: 100%;
    }
    .main  #searchBox {
      display: block;
      width: 100%;
      height: 100%;
      padding: 5px 10px 5px 10px;
      border: 1px solid #19b955;
      box-sizing: border-box;
    }
    .main #btn {
      position: absolute;
      display: block;
      right: 0;
      top: 0;
      width: 20%;
      height: 100%;
      line-height: 100%;
      background: #19b955;
      font: 400 18px Arial;
      color: #fff;
      text-align: center;
      border: none;
      outline: none;
    }
    .show {
      width: 80%;
      border: 1px solid #ccc;
    }
    .show ul {
      width: 100%;
      height: 100%;
    }
    .show ul li {
      width: 100%;
      height: 20px;
      padding-top: 5px;
      padding-bottom: 5px;
      text-align:left;
      text-indent:10px;
      cursor:pointer;
    }
    .show ul li:hover {
      background: #ccc;
    }
  </style>
  <script src="./libs/jquery.min.js"></script>
  <script src="./libs/artTemplate-master/dist/template.js"></script>
</head>
<body>
  <div class="main">
      <div class="search">
        <input type="text" id="searchBox">
      </div>
      <input type="button" value="搜 索" id="btn">
      <div class="show" style="display: none;">
        
      </div>
  </div>
  <!-- 模板引擎 -->
  <script type="text/template" id="tpl">
    <ul>
      {{each datas as value index}}
        <li>{{value.word}}</li>
      {{/each}}
    </ul>
  </script>
  <script>
    /* 2.创建搜索引擎返回来数据的回调函数,解析数据 */
    function suggest_so(datas){
      // console.log(datas);
      var html = template('tpl',{"datas":datas.result});
      $('.show').html(html);
    }

    /* 1.添加键盘事件,获取输入的值 */
    document.getElementById('searchBox').onkeyup = function () {
      var keyword = this.value;
      /* 去掉数据开始和结束的空格 */
      value = keyword.trim();
      if(value.length > 0) {
        /* 显示隐藏的div */
        document.getElementsByClassName('show')[0].style.display = 'block';
        /* 利用 ajax 跨域访问 */
        $.ajax({
          url:"https://sug.so.360.cn/suggest?callback=suggest_so&encodein=utf-8&encodeout=utf-8&format=json&fields=word&word=" + value,
          type:"get",
          dataType:"jsonp",
          jsonp:"callback",
          success: function (datas){
            suggest_so(datas);
          }
        })
      } else {
        document.getElementsByClassName('show')[0].style.display = 'none';
      }
    }
    /* 3.增加鼠标移入样式,浏览器渲染完毕,li是keyup事件结束以后追加到html上的,如果
    直接给li绑定事件,是获取不到元素的,这时我们需要事件委托 */    

    /* 问题:实现不了!!!用C3的hover模拟..
    $('ul').on("mouseover",'li',function () {
      this.style.background = "#efefef";
    });
    $(".show>ul").on("mouseout","li",function () {
        this.style.background = "white";
    }); */

    
  </script>
</body>
</html>

效果:

已上传到文件

猜你喜欢

转载自www.cnblogs.com/houfee/p/9333189.html