vue請求接口獲取數據的實現及跨域問題

前言

本文基於vue-cli3

一、通過api接口獲取數據

vuejs中請求接口,大體分爲兩種方式:vue-sourceaxios。它們都是經過良好封裝的http請求插件。

下文將簡單介紹一下使用方法。

1. vue-source

略講,詳情見這篇博客

安裝

首先,安裝該插件:

 

npm install vue-source --save

然後,在項目src/main.js中,通過全局方法Vue.use()使用該插件:

 

import VueSource from 'vue-source'

Vue.use(VueSource)

使用

在data中定義好接口和接收的數據類型,然後,調用this.$http.get()函數進行get請求即可,代碼如下:

 

data () {
  return {
    apiUrl: 'https://xxxxx',
    users: []
  }
},
methods: {
},
created () {
  this.$http.get(this.apiUrl).then((response) => {
    console.log(response)
  }, (error) => {
    console.log('error:', error)
  })
}

代碼解釋:$http.get().then()是get函數請求返回後才調用的函數。then()函數的中兩個參數是匿名函數。上述代碼使用了ES6新增了箭頭函數(即參數指向函數),也可以寫成以下形式:

 

this.$http.get(this.apiUrl).then(function (response) {
  console.log(response)
}, function (error) {
  console.log('error:', error)
})

2. axios

安裝

 

npm install axios

使用

axios庫的主要請求函數有:

 

axios.request(config)
axios.get(url[, config])  // 表示 axios.get(url, config) 和 axios.get(url) 都被允許
axios.delete(url[, config])
axios.head(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]])
axios.patch(url[, data[, config]])

config對象的詳細屬性、請求的後續then()/catch()操作、配置的默認值/defaults等等,見 Axios 中文說明

(以下純屬個人觀點

爲了更好地進行模塊間的解耦,在vue-cli3構建的項目的src\目錄下,創建api\目錄,將項目所有需要進行的請求的配置封裝到該目錄下。

此處示例只封裝到一個api.js文件,如下:

 

// src/api/api.js
import axios from 'axios'

// 允許跨域攜帶cookie
// axios.defaults.withCredentials = true;

export const uploadelf = () => {
    return axios.request({
        method: 'post',
        url: 'http://xxxxx.xxx/api/uploadelf'
    })
}

export const start = () => {
    return axios.request({
        method: 'get',
        url: 'http://xxxxx.xxx/api/start'
    })
}

export const getDisassemble = (funName = 'main') => {
    return axios.request({
        method: 'post',
        url: 'http://xxxxx.xxx/api/disassemble',
        data: {
            funName
        }
    })
}

其中,每個函數返回一個調用請求後的對象,相當於設計模式中的工廠方法

如此封裝的好處是,用戶使用時,並不需要知道某個請求的請求url和請求方式

當你需要在其它模塊中進行相應的請求時,只需要import導入api.js中相應的函數變量並調用即可,如:

 

// src/view/main.vue

...

<script>
// 導入相應的請求函數
import {uploadelf, start, getDisassemble} from '../api/api'

export default {
  data() {
    return {
      assemb: []
    }
  },
  methods: {
    click_uploadelf() {
      // 調用該工廠方法進行請求返回一個對象,再通過對象的then(), catch()方法進行後續操作
      uploadelf().then(resp => {
        console.log('uploadelf --->', resp.data);
      }).catch(error => {
        console.log(error);
      });
    },
    click_start() {
      start().then(resp => {
        console.log('start --->', resp.data);
      }).catch(error => {
        console.log(error);
      });
    },
    click_getDisassemble() {
      getDisassemble('main').then(resp => {
        console.log('getDisassemble --->', resp.data);
        this.assemb = resp.data.message;
      }).catch(error => {
        console.log(error);
      });
    }
  }
}
</script>

補充

js的請求屬於異步操作(不需要等請求完成,函數直接執行結束)。所以,需要通過回調函數來實現請求完成的後續操作。

axios主要利用ES6 Promise來實現異步請求的後續操作。

同時,異步請求會導致請求並行的情況。多個請求之前不能太接近。

二、跨域問題

1.問題

如果是本機localhost:8000測試,可能會出現跨域問題,打開瀏覽器會看到如下報錯:

跨域問題.png

2.補充

  • 當兩個域具有相同的協議(如http), 相同的端口(如80),相同的域名如www.baidu.com,那麼我們就可以認爲它們是在相同的域中(協議,域名,端口都必須相同)。

  • 跨域,就是指協議、域名、端口其中一個或多個不一致的情況下,從當前域去訪問另一個域。

  • 出於安全考慮(防止跨域攻擊 XSS、CSRF),瀏覽器會禁止跨域的請求訪問。其實,同源策略是一種約定,它也是瀏覽器最核心也最基本的安全功能。

3.解決

跨域問題解決有很多方式,以下主要講兩種。

CROS(跨域資源共享)

前端Vue,設置axios允許跨域帶cookie(默認不帶cookie),如下:

 

// axios全局配置,允許跨域帶cookie
axios.defaults.withCredentials = true;

後端:

跨域請求後的響應頭中需要設置:

  • Access-Control-Allow-Origin爲發起請求的主機地址。

  • Access-Control-Allow-Credentials,當它被設置爲true時,允許跨域帶cookie,但此時Access-Control-Allow-Origin不能爲通配符*

  • Access-Control-Allow-Headers,設置跨域請求允許的請求頭。

  • Access-Control-Allow-Methods,設置跨域請求允許的請求方式。

Vue代理

vue-cli自帶代理功能,由node服務器實現。

在項目根目錄下新增vue.config.js項目配置文件,然後配置代理:

 

// 修改配置後一定要 重新npm run serve !!!
module.exports = {
    devServer: {
        // vue項目啓動時的ip地址和端口
        host: 'localhost',
        port: 8000,
        proxy: {
            // 匹配所有以 /api 開頭的url
            '/api': {
                // 請求的目標主機
                target: 'http://dev3.airdb.io:8080',
                changeOrigin: true,
                ws: true
                // 這樣重寫會把路徑中 /api 消去
                // pathRewrite: {
                //   '^/api': '/api'
                // }
            }
        }
    }
}

設置代理後,本地nodejs服務器會將目標主機的url代理到vue項目的url

如:

訪問http://dev3.airdb.io:8080,會轉變成訪問http://localhost:8080,再由http://localhost:8080轉發請求到http://dev3.airdb.io:8080

這樣,就成了同域請求,瀏覽器不會進行限制。但實際上,還是請求了目標主機,只是欺騙了瀏覽器。

由於Vue代理需要利用node服務器,所以只適用於本地npm run serve調試時。

當項目部署到服務器時,可以使用CROS方式、nginx反向代理等方式。

nginx反向代理

只需要在nginx.conf配置文件的vue項目對應的server中,添加:

 

# 匹配vue項目中所有以/api開頭的請求url
location /api {
    include  uwsgi_params;
    proxy_pass   http://0.0.0.0:8081; # 要代理訪問的後端url
}

完整示例如下:

 

server {
    listen       8000;
    listen       80;
    server_name  _;
    root         /pathto/vue_project/;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    location / {
        index index.html;
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }

    location /api {
        include  uwsgi_params;
        proxy_pass   http://0.0.0.0:8081;
    }
}



作者:dounine
鏈接:https://www.jianshu.com/p/e935a8f81971
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章