vue/iview的table单元格可编辑,可上下键切换,小键盘enter可选中下一个

本文主要是介绍vue/iview的table单元格可编辑,可上下键切换,小键盘enter可选中下一个,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在开发过程中,前后至今遇到好几次的编辑输入框编辑情况,4.24之前的版本,虽然改进好几次操作,但是都是用render函数实现,发现有时并不是很好操作,而且隐藏好几个bug,今天(2019-7-19)发布一个新版,目前无发现bug,而且监听键盘更灵活。废话不多说,上代码

 

2019-04-24版本

因为需要多列可编辑表格,直接用render函数,isNum代表这个数是否需要只允许输入小数点

有一点要特别注意,表格展示的数据用tableData,然后深拷贝一组数据,copyTableData,不然实际过程中发现赋值的时候,容易失去焦点

columns的代码如下:

storeColumns: [{title: '序号', type: 'index', align: 'center', fixed: 'left', width: 60},{title: '供应商', key: 'VenderName', align: 'center', fixed: 'left', width: 180},{title: '商品名称', key: 'GoodsName', align: 'center', fixed: 'left', width: 180},{title: '商品条码', key: 'BarCode', align: 'center', width: 180},{title: '品类', key: 'CategoryName', align: 'center', width: 180},{title: '单位/规格', key: 'SpecUnit', align: 'center', width: 180},{title: '保质期', key: 'ShelfLife', align: 'center', width: 180},{title: '销售量', key: 'Qty', align: 'center', width: 180},{title: '同期总销售额', key: 'SaleValue', align: 'center', width: 180},{title: '同期毛利额', key: 'GrossProfit', align: 'center', width: 180},{title: '同期毛利率(%)', key: 'RateOfMargin', align: 'center', width: 180},{title: '昨日库存总量', key: 'CloseQty', align: 'center', width: 180},{title: '建议补货量', key: 'SRQ', align: 'center', width: 180},{title: '订货周期', key: 'OrderCycle', align: 'center', width: 180},{title: '门店订货量', key: 'OrderQtyShop', align: 'center', width: 180, render: (h, params) => {return this.renderInput(h, params, 'OrderQtyShop', 1)}},{title: '预计售完时间', key: 'SellOutDate', align: 'center', width: 180, render: (h, params) => {return this.renderInput(h, params, 'SellOutDate')}},{title: '陈列位置', key: 'POD', align: 'center', width: 180, render: (h, params) => {return this.renderInput(h, params, 'POD')}},{title: '进价', key: 'CostPrice', align: 'center', width: 180},{title: '平均售价', key: 'AvgPrice', align: 'center', width: 180},{title: '计划促销价', key: 'PlanPromPrice', align: 'center', width: 180, render: (h, params) => {return this.renderInput(h, params, 'PlanPromPrice', 1)}},{title: '备注', key: 'Notes', align: 'center', width: 280, render: (h, params) => {return this.renderInput(h, params, 'Notes')}}
],

 renderInput的代码如下,如果有一些功能不需要刻意自己删除,代码有一点乱,可以取自己需求的

renderInput (h, params, values, isNum) {
// 设置一个class,方便待会进行操作domlet ref = values + params.row._index + 'n'return h('Input', {class: [`${ref}`],props: {// 给予初始值value: params.row[values],},on: {'on-blur': (e) => {// 失去焦点时赋值this.$set(this.copyTableData[params.row._index], values, this.changeValue)},'on-focus': () =>{// 获取焦点时,给changeValue中间变量赋值,且选中当前值this.changeValue = this.copyTableData[params.row._index][values]setTimeout(()=> {document.getElementsByClassName(`${ref}`)[0].children[1].select()})}},nativeOn: {keydown: (event) => {// 监听键盘变化,input上下框可以通过上下键切换if (event.keyCode === 38) {if (this.cando) {return}this.cando = truesetTimeout(() => {this.cando = falselet name = values + (params.row._index - 1) + 'n'document.getElementsByClassName(`${name}`)[0].children[1].focus()}, 50)}if (event.keyCode === 40) {if (this.cando) {return}this.cando = truesetTimeout(() => {this.cando = falselet name = values + (params.row._index + 1) + 'n'document.getElementsByClassName(`${name}`)[0].children[1].focus()}, 50)}},input: (e) => {// 项目要求只允许输入三位小数点,直接操作dom赋值let val = e.target.valueif (isNum) {val = val.replace(/[^\d.]/g, "");  //清除“数字”和“.”以外的字符  val = val.replace(/\.{2,}/g, "."); //只保留第一个. 清除多余的  val = val.replace(".", "$#$").replace(/\./g, "").replace("$#$", ".");val = val.replace(/^(\-)*(\d+)\.(\d\d\d).*$/, '$1$2.$3');console.log(val)setTimeout(() =>{document.getElementsByClassName(`${ref}`)[0].children[1].value = val}, 2)this.changeValue = val} else {this.changeValue = val}}},key: ref})
},

2019-7-19效果如图

 1.HTML主要用slot进行操作,需要添加一个class,方便后续dom操作

// 主要利用iview 的slot进行操作
// keyup.native 监听按钮事件
// inputName 监听输入事件,主要限制数字等输入
<Table :columns='tableColumns' :data='tableData'><template slot-scope='{ row, index }' slot='danjia'><Input @input="inputName($event, row, index, 'danjia')" class="danjia" @keyup.native="handleKeyup($event, index, 'danjia')" :value='row.danjia'></Input></template><template slot-scope='{ row, index }' slot='shuliang'><Input @input="inputName($event, row, index, 'shuliang')" class="shuliang" @keyup.native="handleKeyup($event, index, 'shuliang')" :value='row.shuliang'></Input><span>{{row.danwei}}</span></template><template slot-scope='{ row, index }' slot='zengsong'><Input @input="inputName($event, row, index, 'zengsong')" class="zengsong" @keyup.native="handleKeyup($event, index, 'zengsong')" :value='row.zengsong'></Input></template><template slot-scope='{ row, index }' slot='jishu'><Input @input="inputName($event, row, index, 'jishu')" class="jishu" :value='row.jishu' @keyup.native="handleKeyup($event, index, 'jishu')"></Input><span>{{row.danwei}}</span></template><template slot-scope='{ row, index }' slot='jizhong'><Input @input="inputName($event, row, index, 'jizhong')" class="jizhong" :value='row.jizhong' @keyup.native="handleKeyup($event, index, 'jizhong')"></Input><span>kg</span></template><template slot-scope='{ row, index }' slot='jianshu'><Input @input="inputName($event, row, index, 'jianshu')" class="jianshu" @keyup.native="handleKeyup($event, index, 'jianshu')" :value='row.jianshu'></Input><span>{{row.danwei}}</span></template><template slot-scope='{ row, index }' slot='yuanchandi'><Input @input="inputName($event, row, index, 'yuanchandi')" class="yuanchandi"  @keyup.native="handleKeyup($event, index, 'yuanchandi')" :value='row.yuanchandi'></Input></template><template slot-scope='{ row, index }' slot='shengcanriqi'><DatePicker type="date" placeholder="Select date" @keyup.native="handleKeyup($event, index, 'shengcanriqi')" class="shengcanriqi"></DatePicker><!-- <Input @input="inputName($event, row, index, 'shengcanriqi')" class="shengcanriqi" @keyup.native="handleKeyup($event, index, 'shengcanriqi')" :value='row.shengcanriqi'></Input> --></template><template slot-scope='{ row, index }' slot='baozhiqi'><Input @input="inputName($event, row, index, 'baozhiqi')" class="baozhiqi" @keyup.native="handleKeyup($event, index, 'baozhiqi')" :value='row.baozhiqi'></Input></template></Table>

2.表头和表格数据

// 表头数据格式定义,咳咳,忽略拼音的key
tableColumns: [{ type: 'selection', align: 'center', width: 50, fixed: 'left' },{ title: '序号', type: 'index', width: 80, align: 'center', fixed: 'left' },{ title: '编码', key: 'num', align: 'center', fixed: 'left', width: 100 },{ title: '品名', key: 'pinming', align: 'center', fixed: 'left', width: 100 },{ title: '单位', key: 'danwei', align: 'center', width: 80 },{ title: '单价', key: 'danjia', width: 100, slot: 'danjia', renderHeader: (h, params) => this.renderHeader(h, params, '单价(元)', 'danjia') },{ title: '数量', key: 'shuliang', slot: 'shuliang', width: 100, align: 'center' },{ title: '金额(元)', key: 'jine', align: 'center', width: 100, renderHeader: (h, params) => this.renderHeader(h, params, '金额(元)', 'jine') },{ title: '赠送数量', key: 'zengsong', slot: 'zengsong', width: 100, align: 'center' },{ title: '计数', key: 'jishu', align: 'center', width: 100, slot: 'jishu', renderHeader: (h, params) => this.renderHeader(h, params, '计数', 'jishu') },{ title: '计重', key: 'jizhong', align: 'center', width: 100, slot: 'jizhong', renderHeader: (h, params) => this.renderHeader(h, params, '计重', 'jizhong') },{ title: '件数', key: 'jianshu', align: 'center', width: 100, slot: 'jianshu', renderHeader: (h, params) => this.renderHeader(h, params, '件数', 'jianshu') },{ title: '原产地', key: 'yuanchandi', align: 'center', width: 150, slot: 'yuanchandi' },{ title: '生产日期', key: 'shengcanriqi', align: 'center', width: 180, slot: 'shengcanriqi' },{ title: '保质期', key: 'baozhiqi', align: 'center', width: 300, slot: 'baozhiqi' }
],
// 当然是假数据,哈哈哈,后端数据没来,key全部用拼音代替
tableData: [{danwei: '头', num: 1, pinming: '品名1', danjia: 2, shuliang: 2, jine: 2, jishu: 2, jizhong: 3, jianshu: 5},{danwei: '个', num: 1, pinming: '品名2', danjia: 2, shuliang: 2, jine: 2, jishu: 2, jizhong: 3, jianshu: 5},{danwei: '个', num: 1, pinming: '品名2', danjia: 2, shuliang: 2, jine: 2, jishu: 2, jizhong: 3, jianshu: 5},{danwei: '个', num: 1, pinming: '品名2', danjia: 2, shuliang: 2, jine: 2, jishu: 2, jizhong: 3, jianshu: 5},{danwei: 'kg', num: 1, pinming: '品名3', danjia: 2, shuliang: 2, jine: 2, jishu: 2, jizhong: 3, jianshu: 5}
],

3. methods方法的定义,直接操作dom,小键盘enter键向右既下一个,注意需要按顺序写一个对象

// 表头方法定义,由于个别列需要进行输入合计
renderHeader (h, params, name, key) {return h('div', [h('div', name),h('div', {style: {'text-align': 'right'}}, this.addNum[key])])
},// 按键切换
handleKeyup (event, index, key) {// 向上键if (event.keyCode === 38) {// 获取到所有class为[key]的dom列表let doms = document.getElementsByClassName(key)if (!index) {index = this.copyTableData.length}// 选中类表中第index个,向上故而减1,dom里头包含的input,获取焦点以及选中input里的内容let dom = doms[index - 1].getElementsByTagName('input')[0]dom.focus()dom.select()}// 向下键if (event.keyCode === 40) {let doms = document.getElementsByClassName(key)if (+index === this.copyTableData.length - 1) {index = -1}let dom = doms[index + 1].getElementsByTagName('input')[0]dom.focus()dom.select()}// 小键盘回车键if (event.keyCode === 13) {// 小键盘回车因为需要根据class判断下一个,故而有input输入框的全部需要在这按顺序声明let keyName = ['danjia', 'shuliang', 'zengsong', 'jishu', 'jizhong', 'jianshu', 'yuanchandi', 'shengcanriqi', 'baozhiqi']let num = 0if (key === keyName[keyName.length - 1]) {if (index === this.copyTableData.length - 1) {index = 0} else {++index}} else {keyName.map((v, i) => {if (v === key) {num = i + 1}})}let doms = document.getElementsByClassName(keyName[num])let dom = doms[index].getElementsByTagName('input')[0]dom.focus()dom.select()}
},
// 输入赋值,记得不直接给tableData赋值,而是深度拷贝一个,不然从新渲染时会失去焦点
inputName (value, row, index, key) {let ret = this.regular(value)let dom = document.getElementsByClassName(key)setTimeout(() => {dom[index].children[1].value = ret})this.copyTableData[index][key] = value
},
// 正则验证,限定输入数字,到时可根据参数选择要不要验证,这里自己看是否需要
regular (value) {value = value.replace(/[^\d.]/g, '') // 清除"数字"和"."以外的字符value = value.replace(/[^\d.]/g, '') // 清除"数字"和"."以外的字符value = value.replace(/^\./g, '') // 验证第一个字符是数字而不是value = value.replace(/\.{2,}/g, '.') // 只保留第一个. 清除多余的value = value.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.')console.log('value2:' + value)value = value.replace(/^(-)*(\d+)\.(\d{3}).*$/, '$1$2.$3') // 只能输入两个小数return value
}

4.computed计算属性监听头部数字变化

computed: {addNum () {let nums = {jine: 0,jishu: 0,jizhong: 0,jianshu: 0}this.copyTableData.map(v => {nums.jine += +v.jinenums.jishu += +v.jishunums.jizhong += +v.jizhongnums.jianshu += +v.jianshu})return nums}
},

 

这篇关于vue/iview的table单元格可编辑,可上下键切换,小键盘enter可选中下一个的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/702096

相关文章

vue基于ElementUI动态设置表格高度的3种方法

《vue基于ElementUI动态设置表格高度的3种方法》ElementUI+vue动态设置表格高度的几种方法,抛砖引玉,还有其它方法动态设置表格高度,大家可以开动脑筋... 方法一、css + js的形式这个方法需要在表格外层设置一个div,原理是将表格的高度设置成外层div的高度,所以外层的div需要

使用Python合并 Excel单元格指定行列或单元格范围

《使用Python合并Excel单元格指定行列或单元格范围》合并Excel单元格是Excel数据处理和表格设计中的一项常用操作,本文将介绍如何通过Python合并Excel中的指定行列或单... 目录python Excel库安装Python合并Excel 中的指定行Python合并Excel 中的指定列P

Vue项目中Element UI组件未注册的问题原因及解决方法

《Vue项目中ElementUI组件未注册的问题原因及解决方法》在Vue项目中使用ElementUI组件库时,开发者可能会遇到一些常见问题,例如组件未正确注册导致的警告或错误,本文将详细探讨这些问题... 目录引言一、问题背景1.1 错误信息分析1.2 问题原因二、解决方法2.1 全局引入 Element

详解如何在React中执行条件渲染

《详解如何在React中执行条件渲染》在现代Web开发中,React作为一种流行的JavaScript库,为开发者提供了一种高效构建用户界面的方式,条件渲染是React中的一个关键概念,本文将深入探讨... 目录引言什么是条件渲染?基础示例使用逻辑与运算符(&&)使用条件语句列表中的条件渲染总结引言在现代

详解Vue如何使用xlsx库导出Excel文件

《详解Vue如何使用xlsx库导出Excel文件》第三方库xlsx提供了强大的功能来处理Excel文件,它可以简化导出Excel文件这个过程,本文将为大家详细介绍一下它的具体使用,需要的小伙伴可以了解... 目录1. 安装依赖2. 创建vue组件3. 解释代码在Vue.js项目中导出Excel文件,使用第三

Java实现Excel与HTML互转

《Java实现Excel与HTML互转》Excel是一种电子表格格式,而HTM则是一种用于创建网页的标记语言,虽然两者在用途上存在差异,但有时我们需要将数据从一种格式转换为另一种格式,下面我们就来看看... Excel是一种电子表格格式,广泛用于数据处理和分析,而HTM则是一种用于创建网页的标记语言。虽然两

IDEA如何切换数据库版本mysql5或mysql8

《IDEA如何切换数据库版本mysql5或mysql8》本文介绍了如何将IntelliJIDEA从MySQL5切换到MySQL8的详细步骤,包括下载MySQL8、安装、配置、停止旧服务、启动新服务以及... 目录问题描述解决方案第一步第二步第三步第四步第五步总结问题描述最近想开发一个新应用,想使用mysq

vue解决子组件样式覆盖问题scoped deep

《vue解决子组件样式覆盖问题scopeddeep》文章主要介绍了在Vue项目中处理全局样式和局部样式的方法,包括使用scoped属性和深度选择器(/deep/)来覆盖子组件的样式,作者建议所有组件... 目录前言scoped分析deep分析使用总结所有组件必须加scoped父组件覆盖子组件使用deep前言

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

React实现原生APP切换效果

《React实现原生APP切换效果》最近需要使用Hybrid的方式开发一个APP,交互和原生APP相似并且需要IM通信,本文给大家介绍了使用React实现原生APP切换效果,文中通过代码示例讲解的非常... 目录背景需求概览技术栈实现步骤根据 react-router-dom 文档配置好路由添加过渡动画使用