zoukankan      html  css  js  c++  java
  • JS之跨域

    1、跨域

    阅读文章:不要再问我跨域的问题了

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

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

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

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

    2、解决跨域的三种方式

    2.1、服务器代理

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

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

    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请求。

    本地案例1:

    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>

     显示效果:

    360搜索跨域案例

    简单实现跨域请求:

    <!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>

    效果:

    利用jQuery实现跨域:

    <!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>

    jsonp封装

    参看:实现一个JSONP

    // 封装
    function jsonp({ url, params, callback }) {
      return new Promise((resolve, reject) => {
        let script = document.createElement('script')
        window[callback] = data => {
          resolve(data)
          document.body.removeChild(script)
        }
        params = { ...params, callback }
        let arrs = []
        for (let key in params) {
          arrs.push(`${key}=${params[key]}`)
        }
        script.src = `${url}?${arrs.join('&')}`
        script.setAttribute('type', 'text/javascript')
        document.body.appendChild(script)
        script.onerror = () => {
          reject(new Error(`fetch ${url} failed`))
          document.body.removeChild(script)
        }
      })
    }
    
    // 设置方法
    const fn = async function (value) {
      let data = await jsonp({
        url: 'https://sug.so.360.cn/suggest/',
        params: {
          encodein: 'utf-8',
          encodeout: 'utf-8',
          format: 'json',
          fields: 'word',
          word: value
        },
        callback: 'suggest_so'
      })
      console.log(data)
    }
    
    // 调用
    fn('北京')
    一个vue的UI库:https://github.com/houfee/light-ui,如果对您有帮助,请star ^-^
  • 相关阅读:
    精彩的漫画小说
    《Java语言精粹》译者序
    群啊群
    围观透明咆哮体
    读《Cassandra权威指南》
    好书什么样?
    一个关于360和腾讯的调查
    Xcode 3.x class ations 以及outlets 去哪里了 ?
    「译」JavaScript 的 MVC 模式
    MAC OS 虚拟机里的control键设置
  • 原文地址:https://www.cnblogs.com/houfee/p/9333189.html
Copyright © 2011-2022 走看看