情况是这样的,今天写了一个字段新增,删除,编辑表格,里面用了Vuetify3提供的v-text-field控件。逻辑是让某个列表中的每行对象的所有列,每列一个input控件,可以自由编辑内容。
结果使用时发现问题,我只要输入一个字符,就会失去焦点,无法继续输入字符,只能再点击input获取焦点。如此一来只能一个个输入。
排查原因。一开始以为是V-model的问题。我替换成:modal-value=“item”之后,输入就不失去焦点了。但是内容的显示出现了错乱,尤其翻页的时候我发现第二页的内容跟第一页是相同的。这肯定不行,我甚至一度以为是分页的锅,修改了几次分页的写法,最后甚至删除了分页器。后来及时醒悟,应该是因为v-model每次输入字符,自动修改了对象内容,而对象包含在列表中,所以对象修改即意味着列表内容修改。由此一来,由于table控件是由列表数据驱动的,所以列表一旦修改,就会触发Table控件的重绘,于是Table里的每行都会重新判断,而我们修改的那一行就会重绘,用新的组件替换旧的组件,导致原来的input失去焦点。
找到了原因,就该想解决的办法。然而我搜了一些方法,感觉都是奇技淫巧,比如说让Table组件和里面的input分别用不同的数据源,这样修改input数据时,触发另一个列表的更新,然后在外面再写逻辑让Table从另一个列表拿值回来,很麻烦。至于Vuetify 3的文档里,给出的CRUD表格示例。它没有用input作表格显示元素,而是用默认的行列显示数据。然后在操作中有一个编辑,然后弹出一个弹窗来编辑。其实思路也蛮好的,但是跟我之前的代码有区别,修改的话动静有点大。而且我想象了一下效果,也有点麻烦。
所以我换了个思路,只要找到一个触发事件,是在比如焦点离开后触发的,这样不就可以实现输入完后再更新数据,也就不会有问题了啊。然而Vuetify3的这个v-text-field里面又只有update这个事件。
这时我想到了,直接用默认的input组件试一试。这里面有个@change事件,是在用户输入回车或者离开输入区域后触发的,里面可以用$event.target.value拿到控件的值。试了一下果然可以。
于是我在找Vuetify 3里有没有v-input之类的基础组件让我借个壳,实现样式上的统一。正在寻找时,我灵机一动,把@change事件写进v-text-field里,试验发现成功了!想想也是,它也是input封装的嘛。由此解决了问题。
好久没有写前端东西了,有些渲染方面的机制确实忘了。加上Vue,JS和组件库混用,跟以往的实践有差异。还有Chatgpt有时会幻想不存在的接口。今后要注意啊。
发表回复