ant-design-vue 快速避坑指南(推荐)


Posted in Javascript onJanuary 21, 2020

ant-design-vue是蚂蚁金服 Ant Design 官方唯一推荐的Vue版UI组件库,它其实是Ant Design的Vue实现,组件的风格与Ant Design保持同步,组件的html结构和css样式也保持一致。 用下来发现它的确称得上为数不多的完整的VUE组件库与开发方案集成项目。

本文主要目的是总结一些开发过程中比较耗时间去查找,文档中没有具体说明的常见问题,同时希望能给新上手此框架的同学提供一些参考作用。 

1.Table对接后台返回数据

针对Table数据格式与后他接口返回数据格式不一致问题,修改 `@/components/table/index.js` 132行起

主要修改pageNo,pageSize,totalCount,data这字段与后台返回字段一致就OK了

result.then(r => {
 this.localPagination = Object.assign({}, this.localPagination, {
  current: r.pageNo, // 这里修改当前分页字段
  total: r.totalCount, // 这里修改总记录数字段
  showSizeChanger: this.showSizeChanger,
  pageSize: (pagination && pagination.pageSize) ||
   this.localPagination.pageSize // 这里修改总记录数当前页数字段
 })
  //r.data中的data修改为返回列表字段
 if (r.data.length == 0 && this.localPagination.current != 1) {
  this.localPagination.current--
  this.loadData()
  return
 }
 !r.totalCount && ['auto', false].includes(this.showPagination) && (this.localPagination = false)
 this.localDataSource = r.data // 返回结果中的数组数据
 this.localLoading = false
});

2.table操作栏参数问题

在table的dataSource中指定的每一个数据中,都必须包含有name为key的对象,而显示出的数据就是相应key对应的数据,dataIndex就用来声明列数据在数据项中对应的key

然而在操作列中,我们一般需要传入不知一项数据,试了一下如下图配置dataIndex,数据并不能正确传入slot-scope中

columns: [
  ...
  {
      title: '操作',
      dataIndex: 'id,text',
      key: 'id',
      scopedSlots: { customRender: 'operation' }
  }

多尝试后发现,其实只要不配置dataIndex就好了。。。slot-scope自定义一个字段,自然就拿到了整行数据

3.table分页组件展示条数

:pagination="{showTotal: total => `共${total}条`}"

4.神奇的最后一个标签隐藏问题

使用可编辑tags过程中值得注意的问题,一般删除某个tag不止是从DOM中删除这个tag,而是需要调接口修改数据,那么这时候如果选择用修改完的数据动态渲染tag列表,并且理所当然地认为动态绑定数据就不需要关心数据手动处理,问题就出现了:

假如一共有5个tag,现在删除第一个tag,并调用接口返回新数据,注意tags默认的删除操作也不是从DOM中删除这个tag,而是将这个tag设置为```display:none```!这就导致了一个很神奇的问题,此时新返回的tags数组长度已经 -1,而它仍然认为当前列表的第一个Tag是隐藏的,最后呈现的效果就是只剩3个Tag,此时再接着删除第一个tag(其实是第二个),那么就只剩1个tag了。。

<a-tag
 v-for="(tag, index) in Tags"
  :key="tag.id"
  :closable="tagCloseable"
  :afterClose="() => handleTagStatus(0,tag)"
  >{{ tag.name }}
</a-tag>

这个问题貌似没什么好的办法,只能放弃绑定动态数据,判断接口调用成功后,再用文档中的手动操作增减数据的办法:

this.Tags = this.Tags.filter(tag => tag.id !== removeTag.id)

5.表单的各种常规操作

单独触发某个字段的校验:

this.form.validateFields(['name'], { force: true })

清除某个字段的值:

this.form.resetFields(`name`,'')

设置表单初始值:

this.form.resetFields(`name`,'')

注意:不初始化的值用undefined而非‘',否则下拉框会不显示placeholder!

自定义文件上传的action函数:

<a-upload :customRequest="upLoad"></a-upload>

upLoad (info) {
  let file = info.file;
  let param = new FormData(); //创建form对象
  param.append('file',file);//通过append向form对象添加数据
  console.log(param.get('file')); //FormData私有类对象访问不到,可以通过get判断值是否传进去
  let config = {
    headers:{'Content-Type':'multipart/form-data'}
  }; 
  this.$http.post(url, param, config).then(res => {
    ...
  })
},

6.接口跨域携带cookie问题

做单点登录时需要在请求头中携带cookie,遇到了很坑人的问题,实际原因是对mock.js的实现不够了解。

还是在`@/src/utils/request.js`,这里创建了axios实例供全局调用,根据axios文档,**在创建** axios 实例时添加:`withCredentials: true`

const service = axios.create({
  baseURL: `${process.env.VUE_APP_BASEURL}/backend`,
  withCredentials: true,
 timeout: 6000 
})

结果发现接口请求仍然不带cookie,无奈试了一下用fetch请求`fetch(url, { credentials: 'include', mode: 'cors' })`,发现可以携带cookie,百思不得其解,两者都是基于promise实现的,但是fetch在写法和拦截请求响应等方面都比较麻烦,全部替换成fetch也不太现实。最后才发现,是mock.js没有注释(`main.js`中注释掉就好了),原来mock.js是通过拦截XHR请求来实现的接口模拟,Axios本质上也是对原生XHR的封装,只不过它是Promise的实现版本,所以它当然被拦截了,而fetch脱离了XHR,这也是fetch请求能正常携带cookie的原因,这里还没有全部梳理清楚,打算在后一篇中详细介绍一下

7.单点登录的实现

全局的路由钩子在`permission.js`中,一般单点登录、权限验证都是在这里处理,这里也不例外。没什么特别的,需要注意的一点就是,不要忘记对页面其他接口的统一无权限处理,和403请求的响应处理。同时画个流程图会更快一些,这里就记录一下吧:

流程图:

ant-design-vue 快速避坑指南(推荐)路由钩子

路由钩子的处理:

router.beforeEach((to, from, next) => {
 // 对403无权限的处理
 if (to.path === '/403') {
  next()
 } else {
  if (roles) {//已登陆
   next()
  } else {
      //获取用户信息,GetUserInfo逻辑如下:
      //status=403 && reject(res),返回包含status;
      //status=1005 && reject(res.data)返回重定向的URL;
      //status=1000 && resolve()
   store
    .dispatch('GetUserInfo') 
    .then(res => {
     next()
    })
    .catch((e) => {
     if (e.status) {
      next({ path: '/403' })
     } else {
            //拼接URL跳去登陆页,登陆成功会重定向回当前页(login_redirect)
      const url = e.substring(0, e.lastIndexOf('redirect')) + 'redirect=' + login_redirect
      window.location.href = url
     }
    })
  }
 }
})

`@/ src/utils/request.js`中接口返回的统一处理:

service.interceptors.response.use((response) => {
  if (response.data.status === 1005){
      //... 同上跳去登陆页
  }else{
    //为返回数据做统一处理
    return response.data
  }
}, err)

7.引入eCharts

1)npm install

2) components下新建barChart.vue ,import echarts from 'echarts',正常操作...

3) resize触发图表自适应

echart有resizeAPI,一般是在图表组件如barChart.vue里面手动监听窗口resize

mounted() {
  window.addEventListener("resize", () => {
    this.chart.resize(); 
  });
},

后面借鉴element-admin, 利用mixins实现了更完善的统一处理方法:

1)定义一个mixin:resize.js

import { debounce } from '@/utils'//防抖函数
export default {
 data() {
  return {
   $_sidebarElm: null
  }
 },
 mounted() {
  this.__resizeHandler = debounce(() => {
   if (this.chart) {
    this.chart.resize()
   }
  }, 100)
  window.addEventListener('resize', this.__resizeHandler)

  this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
  this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
 },
 beforeDestroy() {
  window.removeEventListener('resize', this.__resizeHandler)

  this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
 },
 methods: {
  $_sidebarResizeHandler(e) {
   if (e.propertyName === 'width') {
    this.__resizeHandler()
   }
  }
 }
}

2)@/components/_utils/util.js中添加防抖函数

export const debounce = (func, wait, immediate) => {
 let timeout, args, context, timestamp, result
 const later = function() {
  // 据上一次触发时间间隔
  const last = +new Date() - timestamp
  // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
  if (last < wait && last > 0) {
   timeout = setTimeout(later, wait - last)
  } else {
   timeout = null
   // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
   if (!immediate) {
    result = func.apply(context, args)
    if (!timeout) context = args = null
   }
  }
 }
 return function(...args) {
  context = this
  timestamp = +new Date()
  const callNow = immediate && !timeout
  // 如果延时不存在,重新设定延时
  if (!timeout) timeout = setTimeout(later, wait)
  if (callNow) {
   result = func.apply(context, args)
   context = args = null
  }
  return result
 }
}

3)resize监听方法混入图表组件即可

mixins: [resize]

总结

以上所述是小编给大家介绍的ant-design-vue 快速避坑指南,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
自己的js工具 Cookie 封装
Aug 21 Javascript
跨浏览器的 mouseenter mouseleave 以及 compareDocumentPosition的使用说明
May 04 Javascript
js实现的跟随鼠标移动的时钟效果(中英文日期显示)
Jan 17 Javascript
js处理自己不能定义二维数组的方法详解
Mar 03 Javascript
使用jspdf生成pdf报表
Jul 03 Javascript
jQuery中$.ajax()方法参数解析
Oct 22 Javascript
node中使用es5/6以及支持性与性能对比
Aug 11 Javascript
原生JavaScrpit中异步请求Ajax实现方法
Nov 03 Javascript
node.js多个异步过程中判断执行是否完成的解决方案
Dec 10 Javascript
Vue中控制v-for循环次数的实现方法
Sep 26 Javascript
小程序实现新用户判断并跳转激活的方法
May 20 Javascript
微信小程序实现watch监听
Jun 04 Javascript
Ant Design Vue 添加区分中英文的长度校验功能
Jan 21 #Javascript
python虚拟环境 virtualenv的简单使用
Jan 21 #Javascript
详解vue中v-bind:style效果的自定义指令
Jan 21 #Javascript
vue.js iview打包上线后字体图标不显示解决办法
Jan 20 #Javascript
Angular单元测试之事件触发的实现
Jan 20 #Javascript
vue elementui 实现搜索栏公共组件封装的实例代码
Jan 20 #Javascript
D3.js 实现带伸缩时间轴拓扑图的示例代码
Jan 20 #Javascript
You might like
php中文本操作的类
2007/03/17 PHP
php使用fopen创建utf8编码文件的方法
2014/10/31 PHP
PHP四种基本排序算法示例
2015/04/09 PHP
使用PHPCMS搭建wap手机网站
2015/09/20 PHP
ThinkPHP中类的构造函数_construct()与_initialize()的区别详解
2017/03/13 PHP
PHP自定义函数实现数组比较功能示例
2017/10/19 PHP
详解PHP中的8个魔术常量
2020/07/06 PHP
js常用代码段整理
2011/11/30 Javascript
兼容ie、firefox的图片自动缩放的css跟js代码分享
2013/08/12 Javascript
IE中getElementsByName()对有些元素无效的解决方案
2014/09/28 Javascript
js实现字符串转日期格式的方法
2015/05/20 Javascript
JavaScript实现倒计时代码段Item1(非常实用)
2015/11/03 Javascript
JS获取input file绝对路径的方法(推荐)
2016/08/02 Javascript
IOS中safari下的select下拉菜单文字过长不换行的解决方法
2016/09/26 Javascript
Angularjs实现页面模板清除的方法
2018/07/20 Javascript
jquery层次选择器的介绍
2019/01/18 jQuery
使用Vue调取接口,并渲染数据的示例代码
2019/10/28 Javascript
Vue 微信端扫描二维码苹果端却只能保存图片问题(解决方法)
2020/01/19 Javascript
vue-以文件流-blob-的形式-下载-导出文件操作
2020/08/07 Javascript
深入探究Django中的Session与Cookie
2017/07/30 Python
TensorFlow在MAC环境下的安装及环境搭建
2017/11/14 Python
python之线程通过信号pyqtSignal刷新ui的方法
2019/01/11 Python
python连接、操作mongodb数据库的方法实例详解
2019/09/11 Python
JS原生实现轮播图的几种方法
2021/03/23 Javascript
实习销售业务员自我鉴定
2013/09/21 职场文书
应届生妇产科护士求职信
2013/10/27 职场文书
水污染治理专业毕业生推荐信
2013/11/14 职场文书
大学生就业策划书范文
2014/04/04 职场文书
官僚主义现象查摆问题整改措施
2014/10/04 职场文书
党的群众路线教育实践活动对照检查剖析材料
2014/10/09 职场文书
中学生打架检讨书
2014/10/13 职场文书
幼儿园端午节活动总结
2015/05/05 职场文书
标枪加油稿
2015/07/22 职场文书
golang 比较浮点数的大小方式
2021/05/02 Golang
小程序实现文字循环滚动动画
2021/06/14 Javascript
Java中CyclicBarrier和CountDownLatch的用法与区别
2021/08/23 Java/Android