最近新作了一個項目,由於徹底是另起爐竈,能夠拋開歷史問題,從新嘗試新的思路與解決方案。也兢兢業業的踩坑倆月,把項目第一版跑上線了。這一版主要是保證功能流程沒問題,下一版會對開發流程、性能、錯誤監控等問題進行優化。截至目前記錄的一些問題先抽空整理下。javascript
如題,項目採用vue-cli + es6 + axios
這三個做爲基礎跑起來的,依然是移動端,考慮兼容性 安卓4.1 & ios7.1
,剛開始引入了jq,後續發現徹底不必,就引入了axios的ajax庫,而後其餘採用原生JavaScript
及ES6
進行開發,也沒遇到什麼大的問題。html
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兼容性通常,vue-cli
腳手架中默認沒有對Promise進行pollyfill,在目前的項目中,引用了es6-promise
進行兼容處理,大體也就是在不兼容的狀況下自定義實現一個Promise
這個屬性在開發過程當中屢次用到,我的以爲很好用,但兼容性也堪憂,就在base.js中添加了pollyfill,pollyfill中還用到了Object.defineProperty
,因此若是vue沒法兼容的,這個pollyfill也沒法兼容啦
原生的日期選擇組件用起來不論是在安卓上仍是ios上體驗都很棒,可是安卓4.3及如下不識別,此處經過ua判斷了系統版本,安卓4.3如下采用底部彈窗的方式讓用戶輸入日期,犧牲一部分用戶的體驗。
這個相關的問題另起一篇吧,這次項目採用的是前端路由加多個單頁應用,後端只提供接口及靜態文件服務器,具體開發流程和部署:vue-cli + es6多頁面項目開發及部署。