当前位置: 首页 > Web前端 > vue.js

巧妙利用Vue.extend继承组件实现el-table双击可编辑(不要使用v-if和v-else)

时间:2023-04-01 00:55:58 vue.js

#app{width:100%;高度:100vh;框大小:边框框;padding:50px;}问题描述有一个简单的表格,产品需要双击可编辑看下网上的帖子,大都是dom有两部分,一个是输入框,用来填写编辑状态;另一种是普通标签,用于在非编辑显示状态下呈现单元格文本内容。用v-if和v-else添加一个flag标志,控制编辑状态或显示状态。大致代码如下:{{scope.row.name}}这种方式有适用场景,但是每个el-table-column都必须加上el-input和span以及v-if和v-else。我们来试试动态添加el-input,也就是点击那个单元格,给那个单元格添加el-input使其可以编辑,然后适时去掉。这样,当列数很多的时候,就不用加很多v-if和v-else了。我们先来看看效果图。第一步:给el-table绑定双击事件@cell-dblclick='dblclick',然后在双击事件的回调函数中,可以知道点击了哪一行哪一列,celldom,和点击事件。dblclick(row,column,cell,event){...},这个是饿了么官方提供的,没什么好说的。Step2:关键点Step2.1:cell双击事件后,我们先创建一个el-input标签,然后将被点击的cell的值作为参数props让el-input接收,这样el-input将显示单元格的值,您可以对其进行编辑。问题一:如何创建el-input标签?,客官稍等,下面步骤2.2的答案:将创建的el-input标签替换为原来的cellspan标签,这样就可以看到cell变成了可以输入的输入框了。问题2:如何用新建的el-input标签替换原来的span标签,请稍等,下面会回答步骤2.3的问题。当用户编辑完点击别处,也就是输入框失去焦点时,把el-input输入框的标签去掉,恢复默认的span标签(当然失去焦点的时候,请求到修改数据将被发送)。问题三:如何去掉el-input标签,恢复原来的span标签。等一下,下面的答案将回答这个问题。每次双击创建输入标签进行修改,每次修改后失去焦点,都会恢复默认的单元格显示状态。函数实现了代码思路中的三个问题。一:如何创建el-input标签?我们知道,如果创建一个原生的input标签并指定一个值,是比较简单直接的:avaluetotheinputtagdocument.body.appendChild(input)//给文档body添加input标签,但是el-input标签不能通过上面的方法创建,因为document.createElement()方法可以创建el-input标签,但是dom不认识这个el-input标签,所以页面没有变化。毕竟饿了么的el-input也对input标签进行了两次封装,所以这里我们可以使用Vue.extend()方法继承一个组件并暴露出来,而被继承的组件中还有一个input标签。所以需要使用它,并且可以引入一个新的el输入。关于Vue.extend()的定义,这里不再赘述。有关详细信息,请参阅官方文档。作者之前也写过一篇Vue.extend的文章,传送门:https://segmentfault.com/a/11...首先创建一个.vue文件用于继承//input.vue文件道具:{cellValue:{类型:字符串|Number,default:"",},}然后定义一个data.js文件,继承input.vue文件,暴露//data.jsimportVuefrom"vue";importdefinedInputfrom"./input.vue";//Vue继承了这个输入组件,相当于一个构造函数constinputC=Vue.extend(definedInput);//把它暴露出来,在需要导入的地方exportdefault{inputC,}在页面中导入使用//page。vueimportextendComponentsfrom"./threeC/data";//1.引入newextendComponents.inputC({//2.实例化propsData:{//使用propsData对象传递参数,子组件可以接收cellValueinprops:cellValue,//传递cell的值},}).$mount(cell.children[0]);//3.挂载propsData对象给继承的组件传递参数,或者传递一个函数,继承组件通过这个函数通知外部组件,完整代码见下面细节代码问题二、三:el-input标签和span标签的来回替换使用$mount方法来回替换恢复。$mount可以在父dom元素上追加一个子dom元素,相当于appendChild,这里需要有一个replacement时机是当实例化组件中的el-input失去焦点时通知外部组件,所以可以外部使用,将propsData中的一个函数传递给继承的组件,例如://外部组件传递newextendComponents.inputC({propsData:{cellValue:cellValue,//传递单元格的值saveRowData:this.saveRowData,//传递通知的回调函数,可以在继承的组件中触发},}).$mount(cell.children[0]);saveRowData(params){console.log('收到一个继承组件的消息通知,参数为:',params)}//内部组件失去焦点时通知道具:{cellValue:{类型:字符串|Number,default:"",},saveRowData:Function,//外部,传入一个函数,当el-input失去焦点时,通过这个函数通知外部}blurFn(){//失去焦点,再次抛出,通知外部this.saveRowData({cellValue:this.cellValue,//其他参数});},这样当内层失去焦点时,可以通知外层做一个替换,即重新做一个$mount挂载在celldom上,将el-input换成span,为了进一步理解,我们这里也可以使用span的继承方式,用new来实例化,详见下文完整代码完整代码目录结构threeC--data.js--input.vue--span.vuethree.vue为继承el-input组件input.vueexportdefault{props:{单元格值:{类型:字符串|Number,默认:"",},},};统一继承和暴露data.js文件importVuefrom"vue";importdefinedInputfrom"./input.vue";importdefinedSpanfrom"./span.vue";constinputC=Vue.extend(definedInput);constspanC=Vue.extend(definedSpan);exportdefault{inputC,spanC,}使用继承的三个.vue组件#app{width:100%;高度:100vh;框大小:边框框;padding:50px;}总结使用Vue.extend()方法可以继承一些组件,甚至是一些复杂的组件,在实际的业务场景中,会有巧妙的运用,具体的业务场景具体分析。另外,上面的代码是对el-input的继承。其实我们也可以做el-select的继承。思路和上面类似。这样就可以双击表格中的单元格,选中并更改对应的下拉框,改变el-table的单位值,比如有性别一列,就是这样的形式一个下拉框。道友们可以按照这个思路发散……好记性不如烂笔头,记录一下吧^_^2022-08-25补充~输入框单元格等单元格校验功能有规则限制输入的内容。思路分析指定验证函数和验证函数失败的提示文字,然后作为参数传递给需要实例化的el-input,然后根据验证函数使用传入的验证函数传递出去如果结果通过,则做相应的处理。假设该表有如下校验规则。名称列单元格不能超过6个字符。年龄列单元格不能大于1000岁(并且是数字类型)。家乡列单元格没有限制。效果图如下,方便大家使用代码,笔者特地上传至笔者的github仓库。代码地址如下:https://github.com/shuirongsh...个人建议,直接去作者的github仓库拉下完整代码,运行看看。另外,这个仓库是笔者模仿饿了么UI组件的代码仓库。如果能帮到你,欢迎给个star挥手^_^