1. 使用引号来监听嵌套属性
你可能不知道这一点,我们可以通过使用引号轻松地直接监听嵌套值:
watch {
'$route.query.id'() {
// ...
}
}
2.四目运算符:
:type="scope.row.state ==='已支付'?'success':(scope.row.state ==='处理中'?'warning':'danger')"
3. [] == 0 为true
if 和else if区别
function testIF1(){
var a='1';
if(a=='1'){
console.log(1);
}
if(a.indexOf('1')>-1){
console.log(2);
}
}
function testIF2(){
var a='1';
if(a=='1'){
console.log(1);
}else if(a.indexOf('1')>-1){
console.log(2);
}
}
执行方法testIF1,控制台会输出1,2
执行方法testIF2,控制台只会输出1
在testIF1中,代码会自上而下的挨个对if的条件进行判断,如果符合,就会执行if内的代码,执行完之后,再继续向下进行if判断,如果符合if内的条件,仍然会执行if内的代码。
而在testIF2中,代码也会自上而下的挨个对if的条件进行判断,但这里的if和else if不管有几个,只要遇到一个符合条件的,就进去执行if内的代码,其他的都会被忽略掉,不再执行判断,也不会再运行该if内的代码。
4.封装的字典下拉框,如果两个字典需要联动,一个字典更改,另一个字典下拉重新触发渲染,可以给字典下拉组件增加一个key,不需要watch监听
<el-form-item label="费用类型" prop="costType">
<DictSelect v-model="record.costType" dictCode="COST_TYPE" placeholder="费用类型" @change="changeCostType"/>
</el-form-item>
<el-form-item label="成本要素" prop="costElement" v-if="curCostType !== 'NONE'">
<DictSelect v-model="record.costElement" :dictCode="curCostType" placeholder="成本要素" :key="curCostType"/>
</el-form-item>
5.插槽参数传递问题
子组件table-base:
<slot
v-if="column.customFilter"
name="customFilter"
:customFilterDropdown="{ setSelectedKeys, selectedKeys, column }"
></slot>
父组件index:
<template #customFilter="{ customFilterDropdown }">
<DictSelect
v-if="customFilterDropdown.column.dataIndex == 'constraintType'"
:value="customFilterDropdown.selectedKeys[0]"
mode="combobox"
:dictCode="customFilterDropdown.column.dictCode"
style="width: 188px; margin-bottom: 8px; display: block"
:disabledItems="['COND_MIN']"
@change="(e) => customFilterDropdown.setSelectedKeys(e ? [e] : [])"
>
</DictSelect>
</template>
注意:vue模板中不能使用console,特别注意使用传参方式的使用
把字符串按照 空格 换行符和,进行分割
targetStr.split(/[\s\n]/)
targetStr.split(/[,,\s\n]/)
两个数组取交集
var arr1=[1,2,3,4,5,6,"a","b"]
var arr2=['a','b',1,2]
var arr3=arr1.filter(item=>{
return arr2.includes(item)
})
console.log(arr3);//[ 1, 2, 'a', 'b' ]
//filter()数组的过滤方法,会返回满足条件的元素组成一个新数组
//includes()方法如果在数组中查到该元素则返回true否则返回false
两个数组对象合成一个数组,长度不变,属性叠加
const tableData1 = [{ name: 'a', age: 10 }, { name: 'b', age: 11 }];
const tableData2 = [{ name: 'a', sex: 'man' }, { name: 'b', sex: 'girl' }];
const mergedData = tableData1.map((item) => {
const matchedItem = tableData2.find((data) => data.name === item.name);
return { ...item, ...matchedItem };
});
vue开发中容易忽略的bug点
- rules校验name要和绑定的值值保持一致
- 判断value.length 的时候一定要加一个非空判断,因为后端返回value不能保证是数组类型,可能是null导致报错
- 国际化文件不要写特殊字符,容易报错。“|” 在 vue-i18n 中属于特殊字符(还有{、}、@ 、$),如果要使用的话必须通过插值表达式 {‘|’}
连续分批接口请求
let count = 0
//分批查etl数据
const queryEtl = (allNames) => {
let tableNames = allNames[count]
request({
url: '/te/teBizScene/queryEtlTables',
method: 'GET',
params: { id: editRecord.value.bizSceneId, tableNames: tableNames }
})
.then((res) => {
count++
console.log('res', res)
const dynamicData = res
//如果动态字段有数据返回重组tableData
if (!isNull(dynamicData) && dynamicData.length > 0) {
const mergedData = state.tableData.map((item) => {
const matchedItem = dynamicData.find((data) => data.tableName === item.tableName)
return { ...item, ...matchedItem }
})
console.log('mergedData', mergedData)
state.tableData = cloneDeep(mergedData)
}
})
.finally(() => {
if (count < allNames.length) {
queryEtl(allNames)
} else {
return
}
})
}
onBeforeUnmount(() => {
//关闭弹窗,结束回调接口请求
count = 1000
})
数组包含includes和not-includes
filter(r =>{
return !props.excludeItems.includes(r.value)
})
vue3 部分属性置空操作
//使用Object.assign方法
let resetConf = {
host: null,
port: null,
username: null,
password: null,
database: null,
schema: null
}
Object.assign(resourcesConf, resetConf)
//resourcesConf对象直接赋值会导致其他不需要置空的属性也会被置空
resourcesConf = {
host: null,
port: null,
username: null,
password: null,
database: null,
schema: null
}
//下面方法置空代码丑陋
resourcesConf.host = null
resourcesConf.port = null
loading在finally中处理
检测对象是否为空
const isEmpty = obj => Reflect.ownKeys(obj).length === 0 && obj.constructor === Object;
isEmpty({}) // true
isEmpty({a:"not empty"}) //false
表单校验
1. 动态表单校验
//动态路径校验
let checkDataUrl = (rule) => {
//reduce()方法来遍历urlList.value数组,并在每次迭代时判断dataUrl是否为空。如果为空,就将错误信息添加到累积的acc数组中
const errorMessages = urlList.value.reduce((acc, item) => {
if (isNil(item.dataUrl)) {
acc.push(`${item.techType}${t('system.KPILayout.rule.illegalDataUrl')}`)
} else {
console.log('errorMessages', acc)
}
return acc
}, [])
//rule.field为当前触发项,判断错误信息是否包含在触发项中
if (errorMessages.length > 0 && isIncludesArray(errorMessages, rule.field)) {
return Promise.reject(findArrayItem(errorMessages, rule.field))
} else {
return Promise.resolve()
}
//下面方法也能实现,更优
// const matchItem = urlList.value.find(item =>{
// return item.techType == rule.field
// })
// if (rule.field && isNil(matchItem.dataUrl)) {
// return Promise.reject(`${rule.field}${t('system.KPILayout.rule.illegalDataUrl')}`)
// } else {
// return Promise.resolve()
// }
}
2. 子对象属性校验
const rules = reactive({
editionConf: {
useBizScene: [{ required: true, message: t('system.edition.rule.useBizScene'), trigger: 'blur' }],
techTypes: [{ required: true, message: t('system.edition.rule.techTypes'), trigger: 'blur' }]
}
})
<a-form-item :label="t('system.edition.table.useBizScene')" :name="['editionConf', 'useBizScene']">
<a-radio-group v-model:value="editRecord.editionConf.useBizScene">
<a-radio :value="true">是</a-radio>
<a-radio :value="false">否</a-radio>
</a-radio-group>
</a-form-item>
国际化写法(难点)
1. push内国际化写法
acc.push(`${item.techType}${t('system.KPILayout.rule.illegalDataUrl')}`)
2. 对象key值国际化写法
result.forEach((item) => {
return downloadJson.push({
[t('file.import.rowIndex')]: item.rowIndex,
[t('file.import.headName')]: item.headName,
[t('file.import.originContent')]: item.originContent,
[t('file.import.errorType')]: item.errorType,
[t('file.import.errorContent')]: item.errorContent
})
})
3. 模板label拼接类国际化写法
<a-form-item
:label="`${m.techType}${t('system.KPILayout.table.dataUrl')}`"
:labelCol="labelCol"
:name="m.techType"
:rules="[{ required: true, validator: checkDataUrl, trigger: 'blur' }]"
>
<a-input v-model:value="m.dataUrl" style="width: 350px" :maxlength="128"></a-input>
</a-form-item>
forEach+push 效果等同于map,优先使用map
//看这段代码
result.forEach((item) => {
downloadJson.push({
[t('file.import.rowNum')]: item.rowNum,
[t('file.import.errorMsg')]: item.errorMsg
})
})
//效果等同于
const downloadJson = result.map((item) => ({
[t('file.import.rowNum')]: item.rowNum,
[t('file.import.errorMsg')]: item.errorMsg
}))
vue3 如果子组件想修改父组件数据,直接修改会报错 Getting a value from the props
in root scope of <script setup>
will cause the value to lose reactivity,意思是会失去响应
原代码如下
const props = defineProps({
formType: {
type: String,
default: 'new'
},
record: {
type: Object,
default: () => {}
}
})
const { editRow, metricTypeOptions, graphTypeOptions, changeMetricType, validateName, validateMetricKey } =
useKPILayout()
editRow.value = props.record
修改后
const props = defineProps({
formType: {
type: String,
default: 'new'
},
record: {
type: Object,
default: () => {}
}
})
const { editRow, metricTypeOptions, graphTypeOptions, changeMetricType, validateName, validateMetricKey } =
useKPILayout()
// 使用 watchEffect 保持响应性
watchEffect(() => {
editRow.value = props.record
})```