后端重构,如果接口做好抽象封装,只需要考虑jar之间的兼容性问题,jdk版本不变,基本不用做太大的调整,但是前端就不一样,除了vue框架本身,css的调整,改起来更是让人头疼。前面写了vue2项目升级到vue3经历分享1,vue2项目升级到vue3经历分享2,vue2项目升级到vue3经历分享3,因为没有改造完,于是又写了一篇。还有7天时间,希望能顺利推进。
1 el-table-column外层不能加span
很奇怪,为什么只有两列,其他的不见。
检查代码,第一个不规范的地方,为何el-table-column
外层多了一个<span>
,这个再新框架里面直接就显示不了,更为严谨。
去掉之后,列出来了,说明一个问题el-table-column
再el-table
中很重要,列存在才可以显示。
element-ui
中这么写可以,但是element-plus
中,这种外面加<span>
就不规范了。
一般情况下vue2使用Element UI这个组件库,表格组件的插槽的话一般都是使用v-slot,而vue3使用Element Plus组件库,表格组件中插槽一般为#default,不过不改,也能运行。调整后,问题解决。
2 $event.target使用问题
下面的代码,运行后提示 TypeError: Cannot read properties of undefined (reading 'target')
<el-table-column prop="remark" label="备注" show-overflow-tooltip min-width="120">
<template #default="scope">
<span v-show="!scope.row.isEditCell" style="cursor:pointer">{{scope.row.remark}}
</span>
<el-input v-show="scope.row.isEditCell" v-model="scope.row.remark" @blur="cellBlur(scope.row,scope.column)" @focus="cellFocus(scope.row)" :ref="'remark'+scope.row.id" @keyup.enter.native="$event.target.blur"></el-input>
</template>
</el-table-column>
根据文心一言的指导,调整后代码如下,如此界面可以出来了。
<el-table-column prop="remark" label="备注" show-overflow-tooltip min-width="120">
<template #default="scope">
<span v-show="!scope.row.isEditCell" style="cursor:pointer">{{scope.row.remark}}
</span>
<el-input v-show="scope.row.isEditCell" v-model="scope.row.remark"
@blur="cellBlur(scope.row,scope.column)"
@focus="cellFocus(scope.row)" :ref="el => { if (el) scope.remarkInput = el; }"
@keyup.enter.native="finishEdit(scope.row)"></el-input>
</template>
</el-table-column>
finishEdit(row){
row.isEditCell = false;
},
3 this.$set is not a function
触发cellClick
,这里提示this.$set
不是跟函数,vue3为什么舍弃了this.$set
由于 Vue 3 使用 Proxy 使其数据属性自动成为响应式的,所以可以直接修改对象属性,而无需使用 $set。直接赋值即可。
3 TypeError: Cannot read properties of undefined (reading ‘querySelector’)
下面可以看到项目中前端工程师设计了一个select组件,里面直接操作了dom
,这个却是很忌讳,为啥,看看现在的我就知道了,升级改造,非常麻烦,因为el-select
随便一改造,项目肯定需要花费成本去修复这个问题。然成本从而而来?除非是想防御式编程。但问题是高级工程师随着年龄增长,边界效应递减,低级工程师跳槽涨工资,剩下就是丢给高级工程师的烂摊子,最终承受这些憋屈的就是这些高级工程师。这个也是为什么有些公司招所谓架构师或者技术经理,实际就是去救火的原因。
看之前工程运行的效果,实际就是一个默认全选的select,然后封装了一个控件,何必这么麻烦呢。
基于element-plus
原生控件改造,很难,待我写一个
element-plus
升级到2.4.3
,提示下面的错误
1:26:55 [vite] Internal server error: No known conditions for "./lib/locale/lang/zh-cn" entry in "element-plus" package 11:26:55
Plugin: vite:import-analysis
File: E:/workspace/vuework/acc3/src/App.vue
路径修正为import zhCn from 'element-plus/es/locale/lang/zh-cn'
,问题处理。之所以升级element-plus
,是因为el-select
中2.3.0
中有max-collapse-tags
,这个也就是之前为什么有工程师会写自定义select组件的原因,而2.4.0
可以加水印,2.4.3
可以在select
上下方便的加东西,这个版本差不多就够了
<template>
<el-select
v-model="inputValue"
multiple
clearable
collapse-tags
:max-collapse-tags="2"
style="width: 100%"
>
<template #header>
<el-checkbox
v-model="checkAll"
:indeterminate="indeterminate"
@change="handleCheckAll"
>
全选
</el-checkbox>
</template>
<el-option
v-for="(item,index) in options"
:key="index"
:label="item.name"
:value="item.id"
/>
</el-select>
</template>
<script lang="ts" setup>
import { ref, watch, getCurrentInstance } from "vue";
import type { CheckboxValueType } from 'element-plus'
const { proxy }: any = getCurrentInstance();
defineOptions({
name: "multiSelect"
})
// 属性
const emits = defineEmits(['update:modelValue'])
const props = defineProps({
modelValue:{
type:String,
},
options:{
type:Array,
default:()=>[]
},
defaultProps:{
type:Object,
default:()=> ({label:'name',value:'id'})
}
})
// 参数
const checkAll = ref(false)
const indeterminate = ref(false)
const inputValue = ref<CheckboxValueType[]>([])
// 方法
const handleCheckAll = (val) => {
indeterminate.value = false
debugger
if (val) {
inputValue.value = props.options.map((_) => _.id)
} else {
inputValue.value = []
}
}
watch(()=>inputValue,(val)=>{
// 处理自动勾选
debugger
if (val.value.length === 0){
checkAll.value = false
indeterminate.value = false
} else if (val.value.length === props.options.length) {
checkAll.value = true
indeterminate.value = false
} else{
indeterminate.value = true
}
// 处理表单提交
if (!proxy.$_.isEmpty(val)){
emits('update:modelValue',val.value.join(','))
} else{
emits('update:modelValue','')
}
},{immediate:true,deep:true})
</script>
<style>
</style>
控件使用如下,如此简约易懂
<multi-select :options="expenseList" v-model="form.incomeExpenseIdList" :teleported="false" placeholder="支持多选收支类别"></multi-select>
效果如下:
4 表单查询数据错乱的问题
这个问题更加隐蔽,甚至有些莫名奇妙,this.form
跟当前页面的完全不是一个,怎么会传过来的呢?
查询关键字,可以搜索到这一款来自另外一个页面,那么为什么不是同一个页面会出现form
错乱的问题呢?
应该是出现在多个组件使用了,同一个name,当在递归组件的问题会产生混淆的问题。
5 表头th标签不见了
为什么会出现下面的问题
查看代码,还是挺有想象力的
但显示出来却少了东西
正常情况应该是下面的
处理方案居然是,将th
标签调整一下排版,问题解决,如此问题应该出在vite
编译器
6 type="text"废弃的问题
ElementPlusError: [props] [API] type.text is about to be deprecated in version 3.0.0, please use lin
调整为
link type="primary"
看似解决问题,但是效果却是如下图,为什么鼠标放上去之后,背景已变成一片蓝色
element-plus官网没有这个问题,问题就出现项目中,查找样式el-button--primary:hover
,使用的界面框架重新了样式,把它去掉就可以了。
7 filters被废弃
vue3中filters
被废弃,这个功能看似很好,有管道的作用,但是实则让难以维护,这个道理很简单,当你写过滤器很简单,那么这个代价势必会转义到其他地方。就好比给撒哈拉装上太阳版后,撒哈拉将变成绿洲,但是亚马逊那边一定变成沙漠。看似风马牛不相及,实则蝴蝶效应。vue3废弃filters是正确的。换成method简单多了。
8 native废弃得问题
vue2中@keyup.enter.native
,在vue3中调整为@keyup.enter
9 async处理
当方法增加async
表示该方法就是异步得,那么在form表单校验,注意加上await
,如果写法不对,可能会有问题,例如下图,真正请求时等三个form校验通过后,这里需要先将await
加上,否则到了下面方框得到得一定不是正确的值。
10 el-dialog关闭被调用了两次
点击确定后,仍然会调用cancelDialogs
中的方法,很奇怪。
最简单有效的方案,使用@close.once
,通过once
修饰符,close事件只调用一次。
11 统一调整el-table表头样式
element-ui中比较玛法,啥都要自己写
// table 样式
.el-table th{
background-color: #F4F4F4;
font-weight: normal;
color: #333333;
height: 46px!important;
font-size: 15px;
}
在element-plus中可以按照下面的方式处理
.el-table{
--el-table-header-bg-color:#F4F4F4;
th{
font-weight: normal;
font-size: 14px;
}
}
因为可以看到下面el-table
中用到了哪些变量,赋个值就ok了。