vue-cli + es6 + axios項目踩坑

最近新作了一個項目,由於徹底是另起爐竈,能夠拋開歷史問題,從新嘗試新的思路與解決方案。也兢兢業業的踩坑倆月,把項目第一版跑上線了。這一版主要是保證功能流程沒問題,下一版會對開發流程、性能、錯誤監控等問題進行優化。截至目前記錄的一些問題先抽空整理下。javascript

如題,項目採用vue-cli + es6 + axios這三個做爲基礎跑起來的,依然是移動端,考慮兼容性 安卓4.1 & ios7.1,剛開始引入了jq,後續發現徹底不必,就引入了axios的ajax庫,而後其餘採用原生JavaScriptES6進行開發,也沒遇到什麼大的問題。html

Axios

github地址:github.com/axios/axios前端

在此以前一直用的JQ的$.ajax,引入axios後仍是有一些不同的坑要慢慢習慣。vue

  • 請求參數方式不一致java

    axios中,get請求和post請求攜帶參數的方式不同,具體以下:ios

    axios.get(url, {
                params: {
                    id: 123456
                }
            }).then(res => {})
        axios.post(url, {
                id: 123456
            }).then(res => {})
    複製代碼

    解決方案是基於axios簡單封了一個fetch.js,以簡化、統一調用git

  • 返回值更多信息es6

    在jq的回調函數中,咱們後端返回的數據直接放在參數中,咱們能夠直接取res來用,在axios中,回調函數的參數,包含了更多的信息:github

    • status: 請求狀態碼
    • statusText: 請求狀態描述
    • headers: 響應頭相關信息
    • config: 請求的相關配置
    • request: 當次請求相關信息
    • data: 後端返回的數據 也就是說,在axios的回調函數中,res.data和$.ajax回調函數的res是一致的,而大部分時間,咱們只須要知道res.data而忽略更多信息,這一點在fetch.js中也有優化
  • 發起一次請求卻抓到兩個請求ajax

    兩次請求出如今跨域的前提下,jq中解決跨域問題是經過jsonp的方式,而在瀏覽器的標準中,預檢請求是更優雅的解決方案。簡單說,就是在發生跨越的非簡單請求時,瀏覽器會先發送預檢請求,同服務端確認是否容許接下來的正式請求,若是被容許,則再發送正式請求。

    所以咱們可能發現咱們只發送了一次post請求,但卻抓到兩次請求,別擔憂,這不是bug,是個feature。

  • 跨域請求不帶cookie

    跨域請求默認不發送Cookie和HTTP認證信息。若是要把Cookie發到服務器,一方面要服務器贊成,指定Access-Control-Allow-Credentials字段:Access-Control-Allow-Credentials: true,另外一方面,開發者在發起ajax請求時設置withCredentials爲true,這一點也在fetch.js中作了處理。

    在這裏,當咱們的服務器設置Access-Control-Allow-Credentials: true時,會產生新的問題,在瀏覽器標準中,當服務器中設置Access-Control-Allow-Credentials爲true時,Access-Control-Allow-Origin不能設置爲*,而Access-Control-Allow-Origin: *是咱們經常使用的解決跨域問題的設置。

    此問題的解決方案有兩種,第一種方案是簡單的設置一個白名單;另外一種方案,若是以前設置Access-Control-Allow-Origin: *,此時能夠在服務器配置文件進行設置:先獲取發起跨域請求的源域,而後設置Access-Control-Allow-Origin的值爲獲取到的源域。固然這個設置可能在後端某些配置文件裏,也可能直接在服務器配置文件設置。但思路大概類似。

  • 附:fetch.js

    簡單封裝,主要就是對上面幾個問題進行了處理。

    import axios from 'axios'
    
    const fetch = (
        url, 
        params = {},
        options
    ) => {
    
        let _options = Object.assign({
            method: 'get',
            toastInfo: true,
            withCredentials: true
        }, options)
    
        let [ _params, _data ] = _options.method === 'get' ? [ params, ''] : [ '', params]
    
        return axios({
                method: _options.method,
                url: url,
                params: _params,
                data: _data,
                withCredentials: _options.withCredentials
            })
            .then(res => {
                let _res = res.data
    
                //doSomething
    
                return _res
            })
            .catch(e => {
    
                //doSomething
                //錯誤上報
    
            })
    }
    
    export default fetch
    複製代碼

上面這些問題參考HTTP訪問控制(CORS)大抵都能找到合理解釋。

兼容性

  • Promise

Promise兼容性通常,vue-cli腳手架中默認沒有對Promise進行pollyfill,在目前的項目中,引用了es6-promise進行兼容處理,大體也就是在不兼容的狀況下自定義實現一個Promise

  • Array.prototype.findIndex

這個屬性在開發過程當中屢次用到,我的以爲很好用,但兼容性也堪憂,就在base.js中添加了pollyfill,pollyfill中還用到了Object.defineProperty,因此若是vue沒法兼容的,這個pollyfill也沒法兼容啦

  • Input[type=date]

原生的日期選擇組件用起來不論是在安卓上仍是ios上體驗都很棒,可是安卓4.3及如下不識別,此處經過ua判斷了系統版本,安卓4.3如下采用底部彈窗的方式讓用戶輸入日期,犧牲一部分用戶的體驗。

  • 開發及部署

這個相關的問題另起一篇吧,這次項目採用的是前端路由加多個單頁應用,後端只提供接口及靜態文件服務器,具體開發流程和部署:vue-cli + es6多頁面項目開發及部署

相關文章
相關標籤/搜索