vuetify实现excel表格粘贴效果
vuetify实现excel表格粘贴效果文尾附源码效果实现原理Excel表格中的数据粘贴复制到input表单中监测粘贴事件获取粘贴的数据使用空格分隔字符串将解析的数据赋值列表渲染表单数据1.定义粘贴的数据类型以及条件渲染的数据import{ref}fromvueimport{VForm}fromvuetify/components// 定义粘贴数据的类型classpasteContent{code// 编码num0// 数量// 构造函数constructor(code:string,num:number){this.codecodethis.numnum}// 静态工厂方法 调用pasteContent.createDefault() 会默认生成的初始数据staticcreateDefault():pasteContent{returnnewpasteContent(,0)}}// 定义行数 默认生成初始化的一行数据constcolumnsrefpasteContent[]([pasteContent.createDefault()])constformRefrefVForm|null(null)2.前端代码注意事项分多次粘贴的时候需要传入选中本文框的index实现从选中的区域向下粘贴v-formrefformReftemplatev-for(item, index) in columns:keyindexv-rowclassmt-0v-colcols5lg4!-- 编码 --v-text-fieldv-modelitem.codeclearabledensitycompact:rules[v !!v v.length 7 || 不能为空且长度为7]typetextvariantoutlinedpasteHandlepasteCode($event, index)//v-colv-colcols5lg4!-- 数量 --v-text-fieldv-model.numberitem.numdensitycompact:rulesnumRulestypenumbervariantoutlinedpasteHandlepasteNum($event, index)!-- 删除数据行插槽 --template#appendv-iconcolorerrordensitycompactclickDelcolumn(index)mdi-trash-can-outline/v-icon/template/v-text-field/v-col/v-row/template/v-form3.对应的绑定事件// 监听粘贴编码事件functionHandlepasteCode(event:any,_index:number){// 阻止浏览器的默认粘贴行为event.preventDefault()// 获取格式化后的编码数据constcodespasteFormat(event)// 遍历解析数据for(const[offset,value]ofcodes.entries()){// 获取粘贴框的index下标 如果粘贴后的下标大于源数据行数就新增数据行constindex_indexoffsetwhile(indexcolumns.value.length){columns.value.push(pasteContent.createDefault())}//将数值赋值给columns对应下标if(columns.value[index]){columns.value[index].codevalue}}}// 监听粘贴数量事件functionHandlepasteNum(event:any,_index:number){// 阻止浏览器的默认粘贴行为event.preventDefault()// 获取格式化后的数量数据constnumspasteFormat(event)// 遍历解析数据for(const[offset,value]ofnums.entries()){constindex_indexoffsetwhile(indexcolumns.value.length){columns.value.push(pasteContent.createDefault())}//格式化数据 字符串转换为float类型if(columns.value[index]){columns.value[index].numNumber.parseFloat(value)}}}// 粘贴数据处理functionpasteFormat(event:any){// 获取粘贴数据constclipboardDataevent.clipboardData||window.ClipboardconstpastedDataclipboardData.getData(Text)// 获取粘贴的文本// 格式化数据 去除首尾空格returnformatData(pastedData.trim())}// 格式化输入的数据 按照空格分隔清空空格剔除空字符串数据functionformatData(data:string){returndata.split(/\s/).map(itemitem.trim()).filter(itemitem!)}4.增加删除清空事件// 添加行functionAddcolumns(){columns.value?.push(pasteContent.createDefault())}// 删除行functionDelcolumn(index:number){columns.value.splice(index,1)}// 清空行functionClearColumns(){columns.value[]Addcolumns()}5.表单验证规则// 表单校验规则定义constnumRules[(v:number|string|null|undefined){// 如果值为空null/undefined/空字符串报错if(vnull||vundefined||v){return产品数量不能为空}// 转换为数字检查有效性 默认0转成数值0constnumNumber(v)if(Number.isNaN(num)){return请输入有效数字}// 可选限制为非负数根据业务需求if(num0){return数量不能为负数}returntrue}]6.源码 vue页面templatev-containerv-form refformReftemplate v-for(item, index) in columns:keyindexv-rowclassmt-0v-col cols5lg4!--编码--v-text-field v-modelitem.codeclearable densitycompact:rules[v !!v v.length 7 || 不能为空且长度为7]typetextvariantoutlinedpasteHandlepasteCode($event, index)//v-colv-col cols5lg4!--数量--v-text-field v-model.numberitem.numdensitycompact:rulesnumRulestypenumbervariantoutlinedpasteHandlepasteNum($event, index)!--删除数据库行插槽--template #appendv-icon colorerrordensitycompactclickDelcolumn(index)mdi-trash-can-outline/v-icon/template/v-text-field/v-col/v-row/template/v-formv-col cols12lg8v-btn block colorprimaryprepend-iconmdi-plus-thickroundedxsvariantoutlinedclickAddcolumns添加/v-btn/v-col/v-container/templatescript langtssetupimport{ref}fromvue// 定义粘贴数据的类型classpasteContent{code// 编码num0// 数量// 构造函数constructor(code:string,num:number){this.codecodethis.numnum}// 静态工厂方法staticcreateDefault():pasteContent{returnnewpasteContent(,0)}}// 定义行数 默认生成初始化的一行数据// 手动添加行实现 columns.value?.push(pasteContent.createDefault())constcolumnsrefpasteContent[]([pasteContent.createDefault()])// 添加行functionAddcolumns(){columns.value?.push(pasteContent.createDefault())}// 删除行functionDelcolumn(index:number){columns.value.splice(index,1)}// 清空行functionClearColumns(){columns.value[]Addcolumns()}// 表单校验规则定义constnumRules[(v:number|string|null|undefined){// 如果值为空null/undefined/空字符串报错if(vnull||vundefined||v){return产品数量不能为空}// 转换为数字检查有效性 默认0转成数值0constnumNumber(v)if(Number.isNaN(num)){return请输入有效数字}// 可选限制为非负数根据业务需求if(num0){return数量不能为负数}returntrue}]// 监听粘贴编码事件functionHandlepasteCode(event:any,_index:number){// 阻止浏览器的默认粘贴行为event.preventDefault()// 获取格式化后的编码数据constcodespasteFormat(event)// 遍历解析数据for(const[offset,value]ofcodes.entries()){// 获取粘贴框的index下标constindex_indexoffsetwhile(indexcolumns.value.length){columns.value.push(pasteContent.createDefault())}if(columns.value[index]){columns.value[index].codevalue}}}// 监听粘贴数量事件functionHandlepasteNum(event:any,_index:number){// 阻止浏览器的默认粘贴行为event.preventDefault()// 获取格式化后的数量数据constnumspasteFormat(event)// 遍历解析数据for(const[offset,value]ofnums.entries()){constindex_indexoffsetwhile(indexcolumns.value.length){columns.value.push(pasteContent.createDefault())}if(columns.value[index]){columns.value[index].numNumber.parseFloat(value)}}}// 粘贴数据处理functionpasteFormat(event:any){// 获取粘贴数据constclipboardDataevent.clipboardData||window.ClipboardconstpastedDataclipboardData.getData(Text)// 获取粘贴的文本// 格式化数据returnformatData(pastedData.trim())}// 格式化输入的数据functionformatData(data:string){returndata.split(/\s/).map(itemitem.trim()).filter(itemitem!)}/script