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程序:从命令行接收多个数字,求和并输出结果
    大道至简读后感
    大道至简第一章读后感Java伪代码
    Creating a SharePoint BCS .NET Connectivity Assembly to Crawl RSS Data in Visual Studio 2010
    声明式验证超时问题
    Error message when you try to modify or to delete an alternate access mapping in Windows SharePoint Services 3.0: "An update conflict has occurred, and you must re-try this action"
    Upgrading or Redeploying SharePoint 2010 Workflows
    Upgrade custom workflow in SharePoint
    SharePoint 2013中Office Web Apps的一次排错
    How to upgrade workflow assembly in MOSS 2007
  • 原文地址:https://www.cnblogs.com/houfee/p/9333189.html
Copyright © 2011-2022 走看看