vue antd 使用小结

  • 写在前面
  • 开发基础
  • 问题集锦及解决办法
  • 写在后面


写在前面

从六月底开始,到现在这个项目告一段落,两月有余,从刚开始的一无所知,到现在稍有了解,还是想对这段过程做一个总结,不仅仅是这个组件库的应用,也是对自己这段时间的成长做一个总结回顾。

开发基础

结合Ant Design Vue,基于 vue antd admin进行开发。

问题集锦及解决办法

序号

问题

解决办法

1

调整表格间距

使用表格的size属性,设置表格间距

2

添加按钮背景颜色

使用按钮的type属性,设置背景颜色

3

分页 控制显示

自定义分页配置pagination

4

显示序号

使用表格插槽,添加序号表头

5

批量删除

给表格加上checkable属性,就会显示多选框,再拿到选中的值进行删除

6

单选修改状态

可以使用switch开关

7

树结构默认选中

找到双向绑定的选中值进行赋值就可以

8

分页切换loading

表格loading属性,在查询的时候控制loading属性的值

9

admin设置无法选中

获取当前行的值使用判断语句控制disabled属性的值

10

表单验证

使用表单自定义验证方式,配置对应的正则表达式

11

接口文档

找到封装的axios文件,根据格式,写网络请求api文档

12

输入长度限制

input输入框的maxLength属性,动态绑定长度,限制输入

13

错误状态处理

捕获错误之后,有的数组要进行清空,不能在失败的时候显示之前的数据

14

模态框复用

使用枚举,判断类型

15

代码逻辑

初始化的时候,不要写太多方法,尽量将逻辑处理部分写在外面,例如methods

16

逻辑处理

尽量用一个方法处理,见名之意,调用方法返回结果

17

组件通信

订阅者模式,也可以用在非兄弟组件之间,通过EventBus进行兄弟间组件通讯,一定要在生命周期结束的时候进行销毁

18

知识点补充

js的事件循环、箭头函数中this的使用、return的使用

19

v-if的使用

v-if使用的时候,如果不满足条件,就会销毁v-if所在的元素,可以用来清空表单验证

20

空状态的使用

当页面数据为空的时候显示,通过v-if、v-else控制

21

分页变化控制

操作分页之后要把当前页面数据条数和页面传给后台,重新查询,成功后将数据总条数赋值给对应的分页配置总数变量

22

冒泡事件

增删查改的时候,不能改变选中状态,阻止事件的冒泡,使用vue修饰符.present

23

隐藏/置灰一行的某个按钮

使用v-if判断是否显示,使用条件判断控制disabled属性

24

回车提交

搜索框可以添加 enter-button,输入框和其他的元素可以使用@keydown.enter.native="OK" ,进行提交

25

点击模态框旁边不允许关闭

添加属性 maskClosable:false

26

input清空历史记录

不记住浏览器的密码,使用属性 autocomplete="off"

27

下拉框回显

下拉框(单选框)使用的时候注意需要的是什么类型的数据,要给相应的数据才能显示,选中的数据一定是整个数据源数组里的东西,但是要跟选择框需要的数据类型对应才能正确显示。树形结构数据从子级找父级数据的时候,先把数据打平,再遍历,就能拿到对应的父级id,存session会存在误差,操作同步但是数据并不同步

28

对象转换为数组

Object.keys(obj)

29

搜索框加防抖

传入对应的网络请求方法名,和延迟时间,回调此方法时加上延时

30

数据长度溢出

使用css样式控制,数据只显示一行还是两行,表格中有ellipsis属性,设置表头宽度,其他的使用插槽,在插槽上加类去控制样式,搜css省略号,就有对应的代码,还可以定义行间距

31

悬浮提示

气泡提示 a-tooltip组件,还可以控制卡片显示效果

32

模块分割

加上分割线<a-divider dashed />

33

树选择CheckBox和文字同步

改变属性:selectable="false"

34

删完当前页数据页面跳转

删除之后判断当前页面是否还有数据,如果没有就默认跳转回第一页,如果有就留在当前页面(总数减一或者批量选中的数量,对pagesize进行取余,为零就跳转回上一页,不为零就留在当前页)

35

序号要按总数据排序

按当前页码-1查询之后,也要给当前页码重新赋值,this.myPagination.current = this.myPagination.current - 1

36

对话框关闭其中的元素没有销毁,显示历史记录

使用v-if

37

checkgroup绑定key要唯一

设置valuelabel,value是选中的值,label是显示出来的值,一般绑定key使用id,不会重复

38

验证不通过按钮置灰

打印this.$refsthis.form看看,里面可用的,传入表单和对话框类型,拿到当前表单,找到每一项的验证状态,加上非空判定,控制按钮样式

39

样式调整

调试的时候,先定位,先取到什么值,按部就班。二分法,不要只会用定位,先确定外层容器,然后二分之后用浮动float,用了浮动之后,overflow的部分要调整,hidden modal labelCol,和wrapperCol都可以设置,每一个表单项都可以设置,尽量选靠近底层的组件,越接近底层,可使用的方法就越多

40

箴言总结

1、今日事今日毕,需求出来的时候就先解决这件事,不能一直拖着到后面,否则会越积越多 2、思路要清晰,要专心解决3、下次面对突发状况之前,先把当前页面改到一种不出错的状态再去做新任务,或者记一下先,回头继续

  1. 显示序号代码
<span slot="num" slot-scope="text,record,index">
		{{ (myPagination.current-1)*myPagination.pageSize+parseInt(index)+1 }}
	</span>
  1. 搜索框加防抖 代码
export function debounce (fn, delay) {
	    let t = null;
	    return () => {
	        if (t !== null) {
	            clearTimeout(t)
	        }
	        t = setTimeout(() => {
	            fn.call(this)
	        }, delay);
	    }
	}
	// 页面中引用,input属性,或者change属性
	<a-input-search @input="debounce" /> 
	export default {
	    name: 'PlantingCost',
	    components: {},
	    // 全局注入
		inject: ['debounces'],
	    data() {
	        return {
	        // 引用
			debounce: this.debounces(
	                () => this.getPlantingCostData(this.keyword),
	                500
	            ),
            }
 		}
	}
  1. 验证不通过按钮置灰 代码
export function putAsh (form, ModalType) {
	  let arr = [];
	  let hass = false;
	  if (form) {
	    form.$children.forEach(e => {
	      if (e.isRequired) {
	        arr.push(e)
	      }
	    })
	    if (modelLength(ModalType, arr) === arr.length && modelError(form.$children) === 0) {
	      hass = false
	    } else {
	      hass = true
	    }
	  } else {
	    hass = modelType(ModalType)
	  }
	  return hass;
	}
	export function modelError (allarr) {
	  return allarr.filter((v) => v.validateState == "error").length
	}
	
	export function modelLength (type, arr) {
	  switch (type) {
	    case 0:
	      return arr.filter((v) => v.validateState === "success").length
	    case 1:
	      return arr.filter((v) => (v.initialValue && (v.validateState != "error" || v.validateState === undefined)) || v.validateState === "success").length
	    case 2:
	      return arr.filter((v) => (v.initialValue && v.validateState != "error") || v.validateState === "success").length
	  }
	}
	
	export function modelType (type) {
	  switch (type) {
	    case 0:
	      return true
	    case 1:
	      return false
	    case 2:
	      return true
	  }
	}
	
	export function getProps (arr) {
	  let newArr = [];
	  for (const key in arr) {
	    newArr.push(key);
	  }
	  return newArr
	}
	//通过一个数组过滤一个对象
	export function filterProps (props, fieldsError) {
	  let selectNewList = {};	//组装过后的对象
	  selectNewList = Object.keys(fieldsError).filter(val =>
	    props.includes(val)
	  ).reduce((obj, key) => {
	    obj[key] = fieldsError[key];
	    return obj;
	  }, {});
	
	  return selectNewList
	
	}
	export function isAllEqual (array) {
	  if (array.length > 0) {
	    return !array.some(function (value) {
	      return value !== array[0];
	    });
	  } else {
	    return true;
	  }
	}
	export default { putAsh };
	// 页面中引用,input属性,或者change属性
	<a-form-model ref="ruleForm" :model="formChange" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol">
	<a-form-model />
	<template slot="footer">
      <a-button key="back" @click="handleCancel(ModalType)"> 取消 </a-button>
     <a-button type="primary" :disabled="putAsh($refs.ruleForm,ModalType)" @click="handleOk(ModalType)">确定</a-button>
    </template>
	
	// 导入
	import { putAsh } from '@/utils/putAsh';
	export default {
	    name: 'PlantingCost',
	    components: {},
	    data() {
	        return {
	        // 引用
			putAsh: putAsh,,
            }
 		}
	}

补充:文档的上传和下载代码

//download 方法
	export function download (data, type, title) {
	    let blob = new Blob([data], { type: 'application/vnd.ms-excel' });
	    let objectUrl = URL.createObjectURL(blob);
	    let link = document.createElement("a");
	    //let cs=res.headers["content-disposition"].split(";")[2].split("filename=")[1]
	    //cs = cs.replace(/\"/g,"");//去掉双引号
	    link.href = objectUrl;
	    //let time = new Date().getFullYear() +'-'+ (new Date().getMonth()+1) +'-'+ new Date().getDate()
	    let time = Date.parse(new Date())
	    if (type === 1) {
	        link.setAttribute("download", title + time + '.xls');
	    } else {
	        link.setAttribute("download", title + time + '.pdf');
	    }
	    document.body.appendChild(link);
	    link.click();
	    document.body.removeChild(link) // 下载完成移除元素
	    window.URL.revokeObjectURL(blob)
	}
	
	<template slot="operation" slot-scope="text, record">
        <div class="btns">
          <a-tooltip placement="topLeft" title="下载PDF">
            <a-button type="primary" :disabled="record.status!='已上传'" @click="downloadFile(record,2)">
              <a-icon type="download" />
            </a-button>
          </a-tooltip>

          <a-tooltip placement="topLeft" title="上传PDF">
            <a-upload class="avatar-uploader" :show-upload-list="false" :customRequest="uploadFile" :data="{ id: record.classifyId }" :before-upload="beforeUpload" @change="handleChange">
              <a-button type="primary">
                <a-icon type="cloud-upload" />
              </a-button>
            </a-upload>
          </a-tooltip>
        </div>
      </template>
	
	//引用
    inject: ['downloads'],
	
	// 方法
	downloadFile(record, type) {
            if (record.status != '未上传') {
                sortFileDownload(record.classifyId)
                    .then(res => {
                        if (res.status == 200) {
                            this.downloads(res.data, type, record.classifyName);
                            this.query(
                                this.myPagination.pageSize,
                                this.myPagination.current
                            );
                        }
                    })
                    .catch(err => {
                        console.log(err);
                    });
            } else {
                this.$notification['error']({
                    message: '操作失败,分类文档尚未上传!',
                });
            }
        },
        handleChange(info) {
            if (info.file.status === 'uploading') {
                this.loading = true;
                return;
            }
        },
        beforeUpload(file) {
            const isPDF = file.type === 'application/pdf';
            //    ||file.type ===  'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ||
            // file.type === 'application/vnd.ms-excel';
            if (!isPDF) {
                this.$message.error('只能上传PDF文件!');
            }
            const isLt100M = file.size / 1024 / 1024 < 100;
            if (!isLt100M) {
                this.$message.error('文件最大不能超过100M');
            }
            return isPDF && isLt100M;
        },
        uploadFile(file) {
            if (this.classifyId != '') {
                const formData = new FormData();
                formData.append('file', file.file);
                sortFileUpload(this.classifyId, formData)
                    .then(res => {
                        if (res.data.success) {
                            this.query(
                                this.myPagination.pageSize,
                                this.myPagination.current
                            );
                        }
                    })
                    .catch(err => {
                        console.log('上传失败', err);
                    });
            }
        },

写在后面

简短的一个总结回顾。大部分来源于平常遇到问题的随手记,问题描述不是很详细,解决办法也不是很详细,下次做项目的也应该要记得改变一下这个习惯,之后再进行回顾的时候也会更加细致一些,还有很多地方需要学习。
路漫漫其修远兮。