跨域解決方案

說到跨域,就必須要知道同源策略.以下是來自百度百科的解釋:同源策略(Same origin policy)是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會受到影響; 可以說Web是構建在同源策略基礎之上的,瀏覽器只是針對同源策略的一種實現。
同源意味着域名, 端口, 協議必須保持完全一致, 否則無法通信.
好了, 問題來了. web前端愈加複雜的今天, 模塊化, 耦合性低, 體積愈加龐大等等因素, 都迫使我們要將前端分割成幾大塊, 實現按需加載. 而此時, 受到同源策略影響, 頁面之間通信成了一個必須解決的問題—我們稱之爲跨域
本人才疏學淺, 只知道三種解決方案:
方案一: 後臺(PHP)在非同源網站拉取數據, 解析(比如爬蟲什麼的)
方案二: jsonp(這個都很熟悉了)
方案三: HTML5新的API—POSTMessage
方案一, 比如獲取’http://36kr.com/feed‘這個新聞開放接口裏面的數據.主要工作其實在後臺(PHP).總共有兩個PHP文件: superClass.php 和 readXML.php. 前者用於創建父類, 後者用於解析接口裏面的XML數據並傳遞給前端.

superClass.php
<?php 
    class superClass{
        private $obj;
        function __construct(array $arguments = array()){
            if (!empty($arguments)) {
                foreach ($arguments as $property => $argument) {
                    $this->$property = $argument;
                }
            }
        }
    }
 ?>

創建父類的代碼可以說是萬用的, 我也不是太理解, 所以沒法說更多.重點看下readXML.php這個文件

<?php
    require_once 'superClass.php';
    $xml = new DOMDocument(); //創建空XML文檔
    $xml->load('http://36kr.com/feed'); //加載數據
    $main = $xml->getElementsByTagName('item'); //獲取所有數據
    $i = 0; //一次請求拉取10條數據
    $arrObj         =Array(); //對象裝進數組

    foreach( $main as $mainEach)
    { //獲取逐條數據
        if ($i++ == 10) {
            echo json_encode($arrObj); //傳給前端頁面
            break;
        }

        $childrenClass = new superClass(); //實例化父類
        // 作者
        $author = $mainEach->getElementsByTagName( "author" );
        foreach ( $author as $authorEach )
        {
            $value = $authorEach->firstChild->nodeValue;
            $childrenClass->author = $value;
        }
        // 標題
        $title = $mainEach->getElementsByTagName( "title" );
        foreach ( $title as $titleEach )
        {
            $value = $titleEach->firstChild->nodeValue;
            $childrenClass->title = $value;
        }
        // 分類
        $category = $mainEach->getElementsByTagName("category");
        foreach ($category as $categoryEach) {
            $value = $categoryEach->firstChild->nodeValue;
            $childrenClass->category = $value;
        }
        // 詳細內容
        $description = $mainEach->getElementsByTagName( "description" );
        foreach ( $description as $descriptionEach )
        {
            $value = $descriptionEach->firstChild->nodeValue;
            $childrenClass->description = $value;
        }
        // 新聞發佈時間
        $pubDate = $mainEach->getElementsByTagName( "pubDate" );
        foreach ( $pubDate as $pubDateEach )
        {
            $value = $pubDateEach->firstChild->nodeValue;
            $monthStr = substr($value, 8, 3);
            $dayStr = substr($value, 5, 2);
            $dayStr = preg_replace("/0/", '', $dayStr);
            $timeStr = substr($value, 17, 5);
            $childrenClass->pubDate = $timeStr.' '.monthTransform($monthStr).$dayStr.'日';
        }
        // 原文鏈接
        $originalLink = $mainEach->getElementsByTagName("link");
        forEach($originalLink as $originalLinkEach){
            $value = $originalLinkEach->firstChild->nodeValue;
            $childrenClass->originalLink = $value;
        }
        array_push($arrObj, $childrenClass);
    }

    // 英文月份轉化爲數字
    function monthTransform($monthStr){
        switch ($monthStr) {
            case 'Jan':
                return '1月';
                break;
            case 'Feb':
                return '2月';
                break;
            case 'Mar':
                return '3月';
                break;
            case 'Apr':
                return '4月';
                break;
            case 'May':
                return '5月';
                break;
            case 'Jun':
                return '6月';
                break;
            case 'Jul':
                return '7月';
                break;
            case 'Aug':
                return '8月';
                break;
            case 'Sep':
                return '9月';
                break;
            case 'Oct':
                return '10月';
                break;
            case 'Nov':
                return '11月';
                break;
            case 'Dec':
                return '12月';
                break;

            default:
                return '格式錯誤';
                break;
        }
    }
?>

我之前用的是angular, 數據傳輸時, 格式限定非常嚴格(必須是純json字符串, 否則會報錯). 後來又換成了Vue.

vueModule.js

var Promise, Vue, index;
define(function(){return {a: '123'};});
$.post('./php/readXML.php', {param1: '1'}, function(data, textStatus, xhr) {
    objEntity = JSON.parse(data); //此時已經取到數據
});

var objEntity = [];

var app = document.getElementById('app');
var news;
require(["jsonp"], function(){
    var interval = setInterval(function(){
        if (objEntity.description != null) {
            news = objEntity.description[0];
            console.log(news);
            var vueMain = new Vue({
                el: '#app',
                data: {message: news}
            });
            clearInterval(interval);
        }
    }, 50);
});

最重要的是中間那段Vue代碼, 其他的可以不必理會

index.html(顯示數據)

<div id="app">
        <div class="item" v-for="(item, index) in items">
            <div class="author">
                <span>投稿人:{{item.author}}</span>
            </div>
            <div class="item-up">
                <div class="item-up-main">
                    <a href="javascript:void(0);" v-on:click="newsShow(index)"><b class="title">{{item.title}}<br/></b><br/><span class="shortCut"></span></a>
                </div>
                <div class="desc"></div>
            </div>
            <div class="item-down">
                <div class="categary">{{item.category}}</div>
                <div style="width:1rem;"></div>
                <div class="time">{{item.pubDate.substr(0, 5)}}</div>
                <div style="width:0.75rem;"></div>
                <div class="time">{{item.pubDate.substr(5, 5)}}</div>
                <div style="width:3rem;"></div>
            </div>
        </div>
    </div>

最後頁面效果如下圖所示(數據是實時刷新的):
這裏寫圖片描述

實時數據如下:
這裏寫圖片描述

發佈了27 篇原創文章 · 獲贊 4 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章