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多页面项目开发及部署

相关文章
相关标签/搜索