最近新作了一个项目,由于彻底是另起炉灶,能够抛开历史问题,从新尝试新的思路与解决方案。也兢兢业业的踩坑俩月,把项目第一版跑上线了。这一版主要是保证功能流程没问题,下一版会对开发流程、性能、错误监控等问题进行优化。截至目前记录的一些问题先抽空整理下。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多页面项目开发及部署。