天天看点

vue + vue-resource + element-ui项目中遇到的问题总结

运营智享遇到的问题(前端)

vue + vue-resource + element-ui + vue-router + node.js + sass 

1. el-table filter tag 使用filter-method处理数据过滤,当该标签下没有数据时标签切换不起作用

  解决: 1.用el-table的filter-change方法处理过滤逻辑,而不用el-table-column的filter-method方法;

        2.filter tag 设置默认值  

          初始化table时, filter-change和filter-method方法都不会调用,所以初始值设置只是改变tag的UI状态,获取不到当前选择的tag值,

          自己设置一个变量tagValue接收tag值,初始化时默认赋值,在将显示的label值相应formatter回显,filter-change时赋值相应的tagValue.

          :filter-value="filterValue" //tag选中状态

  <el-table :data="list" @filter-change="filterChange">

    <el-table-column

      prop="tag"

      :label="tagNameFormatter"

      column-key="instiStatue"

      :filter-multiple="false"

      :filters="instiStatusList"

      :filter-method="filterTag"

      :filtered-value="filteredValue"

      :formatter="statusFormatter"

      filter-placement="bottom">

    </el-table-column>

  </el-table>

  tagNameFormatter(){//标签名格式化

    let label = '';

    for(let i = 0 ; i < this.instiStatusList.length; i++){

      if(this.tagValue == this.instiStatusList[i].value){

        label = this.instiStatusList[i].text;

      }

    }

    return label;

  }

  filterChange(filter){//过滤(tag值改变) el-table方法

    this.filteredValue = [];

    this.filteredValue.push(filter.instiStatus[0]);

    this.tagValue = filter.instiStatus[0];

    this.getList();//查询列表数据

  }

  filterTag(value, row){//过滤(tag值改变) el-table-column方法

  }

  statusFormatter(row, column){//状态格式化

    let label = '';

    for(let i = 0 ; i < this.instiStatusList.length; i++){

      if(row.status == this.instiStatusList[i].value){

        label = this.instiStatusList[i].text;

      }

    }

    return label;

  }

2. loading遮罩层  ie9 遮罩全透明时,可以点击到遮罩层下的元素

  解决: .loading{background: rgba(255, 255, 255, 0.01);}

3. el-pagination ie9中页码和下一页按钮之间右侧有很大一段空白

    解决: .el-pagination{

      .el-pager{

        li{

          float: left;

        }

      }

    }

4. 同一组件内多次调用pagination或切换tab页pagination,pageSize置为1开始

  切换tab或pagination时将pagination.total = 0, pagination.pageNum = 1;

5. vue检测变化的注意事项

  受现代 JavaScript 的限制 (而且 Object.observe 也已经被废弃),Vue 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。例如:

  var vm = new Vue({

    data:{

      a:1

    }

  })

  // `vm.a` 是响应的

  vm.b = 2

  // `vm.b` 是非响应的

  ue 不允许在已经创建的实例上动态添加新的根级响应式属性 (root-level reactive property)。然而它可以使用 Vue.set(object, key, value) 方法将响应属性添加到嵌套的对象上:

  this.$set(this.someObject,'b',2)

6. el-dialog 在ie9 左右不居中(transform 2d在ie9需加上-ms-前缀)

  //解决方法: 不使用transform

  el-dialog(--small){

    width: 960px;

    height: 770px;

    //加上后三句代码

    transform: none;

    position: static;

    margin: 5rem auto; // 5rem -> 按情况确定

  }

7. 解决输入框背景颜色

  input:-webkit-autofill, textarea:-webkit-autofill, select:-webkit-autofill {

    -webkit-box-shadow: 0 0 0px 1000px #fff inset !important;

  }

8. ie9 v-for 渲染图片list 渲染85张左右后, 图片加载失败

  (由src更新触发的图片资源下载不完整,图片显示x),后面检查发现是内存使用达到6.8G时

  图片加载就会失败,是ie9浏览器内存管理的问题,前端不需要解决,好像也解决不了..

9. ie9 hover元素高度无限增加问题 

  <div class='content'>

    <ul class="list">

      <li class="list_item"> ...... </li>

      <li class="list_item"> ...... </li>

      ......

    </ul>

  </div>

  .content{ width:100%; overflow:auto;}

  如果.list或者.list里的元素设置了:hover的伪类(最常见的是鼠标移入li,改行高亮)并在里面写有属性,hover时就会出现.content高度一直增加的bug.

  bug触发条件:

    1.父级设置overflow:auto;(准确来说是overflow-x:auto;),并且里面的元素宽度超出父级宽度导致横向滚动条出现.

    2.父级元素的任意子元素设有:hover伪类且里面设置有属性(与原属性不一致).

    满足这两个条件,当触发:hover伪类时,bug就会出现.

  解决方案:

    1.给父级设置overflow-x:scroll;(overflow:auto; => overflow-x:scroll;)

      .content{overflow-x:scroll;} -- (子元素宽度未超出父元素宽度时,也会显示滚动条框,视觉体验不太好)

    2.保证父级里的元素不超出父级的宽度,不让父级出现横向滚动条.

    3.保证父级里面的元素没有:hover伪类(这个基本是不可能的..)

    4.给父级加高度

      .content(height:100%;)

10. ie9浏览器对频繁操作dom支持不好,会卡顿甚至卡死,尽量避免大量操作dom元素

11. nginx超时设置(避免post请求处理时间过长,可能出现重复提交的问题)

  nginx 重试机制 proxy_next_upstream http_502 http_504 error timeout invalid_header;

  上面的配置表示,如果后端服务器如下情况,将会把请求转发到下一台后端服务器上。

  error - 在连接到一个服务器,发送一个请求,或者读取应答时发生错误。

  timeout - 在连接到服务器,转发请求或者读取应答时发生超时。

  invalid_header - 服务器返回空的或者错误的应答。

  http_502 - 服务器返回502代码。

  http_504 - 服务器返回504代码。

  继续查看超时时间   

  proxy_read_timeout 15;

  超时时间为15s,所以后端服务器响应慢,nginx没有在15s内收到返回的数据,所以将请求切换到下一台后端机器了,所以,同样的情况下, 请求第二台后端机器时,也没有在规定的时间内得到响应,所以又切换到第三台机器了,最终导致短信发送了三次。 

  几个参数说明:

  proxy_send_timeout     后端服务器数据回传时间(代理发送超时时间)

  proxy_read_timeout      连接成功后,后端服务器响应时间(代理接收超时时间)

  proxy_connect_timeout    nginx连接后端的超时时间,一般不超过75s

  如何解决呢?

    1、第一种办法:因为后端机器无法再进行优化减少响应时间,所以可以更改nginx的超时时间,将原本的15s更改为40s,这样可以保证结果正常返回。

    2、第二种办法 :关闭自动切换到下台机器的功能,即将proxy_next_upstream配置为off。但是这样虽然能解决问题,但是会导致nginx的容错能力下降。

    3、第三种办法:从业务角度出发,本质上我们是需要只发一次短信的。 所以可以采用分布式锁的方式解决。

    以上现象还可能出现在以下的场景:

    1、上传excel,然后服务端处理excel内容,插入到db里面的时候,可能存在多次转发导致数据重复。

    2、post请求处理时间过长,可能出现重复提交的问题。

    本项目中设置了 proxy_send_timeout 180; proxy_read_timeout 180;

12. 后端取回的img URL 赋值给img.src ,ie9会将&转义为&amp;,请求图片资源会出错

  赋值后 imgUrl = imgUrl.replace(/amp;/g,'');

13. 遇到file元素设置cursor:pointer无效的情况

  input[type='file']{

    cursor: pointer;

    font-size: 0;

  }

  经测试,可以通过设置font-size:0;解决,chrome,ie9都可以适用

14. textarea解决maxlength的兼容问题(ie9) 

  <textarea maxlength="10" onBlur="this.value=this.value.substring(0, 10)">

  <el-input type="textarea" model="textareaData" :maxlength="10" @blur="textareaData=textareaData.substring(0, 10)">

15. 文件下载

  1)模版类放前端静态资源

   <a href="static/模版.xlsx" target="_blank" rel="external nofollow" download="模版.xlsx" target="_self"> </a>

   (download属性设置文件名强制下载, ie9不支持)

  2) 文件流下载

    方法一: ie9下载未能解决(识别不了文件类型)

    Vue.http.get('url',{ responseType: 'blob'})

    .then(res => {

      const fileName = "考勤信息.xlsx";

      const blob = response.data;

      if (window.navigator && window.navigator.msSaveOrOpenBlob) {

        window.navigator.msSaveOrOpenBlob(blob, fileName);

      } else {

        let elink = document.createElement("a"); // 创建a标签

        elink.download = fileName;

        elink.style.display = "none";

        elink.href = URL.createObjectURL(blob);

        document.body.appendChild(elink);

        elink.click(); // 触发点击a标签事件

        document.body.removeChild(elink);

      }

    }).catch(err => {})

    方法二: 后台文件流上传到ecs(另一个存储平台),取回文件URL,返回前端下载

  3) URL下载

      指定文件mimeType的文件,浏览器会默认打开预览,添加download属性指定附件名称后会下载,ie9不支持 

      目前解决方法: <a href="url" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" download="模版.xlsx"> </a>直接在新窗口打开,用户另存为

16. 文件上传(使用的pulpload上传插件)

  1) 文件上传返回json数据,ie9提示文件下载,后台改content-type:text/html;

  2) ie9 ajax请求头不能自定义设置,设置不了token,去掉权限校验,可以通过multipart_params传参;

  3) 文件通过后台上传到另一个平台,需要后台指定content-type,不然取回的文件URL都是application/octet-stream类型

    (mp4/mp3 ie浏览器(9,10,  11)识别不了mime类型,不能播放);

    指定类型后的文件,取回的URL在浏览器会直接打开,不能强制下载,mp4在ie会提示下载,

      目前解决方法: <a href="url" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank"> </a>直接在新窗口打开,用户另存为

  4) Chrome上传zip格式文件,弹出选择文件框要延迟7-8s,未解决

    https://blog.csdn.net/mingover/article/details/55045533

    http://www.piaoyi.org/computer/Google-Chrome-input-file-delay-3-5.html

  5) 使用plupload 

    import plupload from 'plupload'

    若要使用图片预览 需引入 moxie.min.js(index.html)

  6) 多文件上传

    用pulpload 直接选择多文件,上传时会调用多次上传接口

    解决: 用pulpload上传单个文件,上传多次,保存返回的fileId, 把fileIdList在通过另一个接口传给后台关联保存.  

17. js实现不提示直接关闭网页窗口

  function closePageForm(){

    window.opener=null;

    window.open('','_self');

    window.close();

  }

18. 解决 ie9 input input删除操作无法触发数据变动监听

  main.js里添加

  (function (d) {

    if (navigator.userAgent.indexOf('MSIE 9') === -1) return;

    d.addEventListener('selectionchange', function() {

      var el = d.activeElement;

      if (el.tagName === 'TEXTAREA' || (el.tagName === 'INPUT')) {

        var ev = d.createEvent('CustomEvent');

        ev.initCustomEvent('input', true, true, {});

        el.dispatchEvent(ev);

      }

    });

  })(document);