vue开发不能不知的小知识

本文介绍了Vue3中如何监听嵌套属性、使用四目运算符进行条件渲染,如何利用`v-if`和`v-else-if`控制代码流程,以及在组件间联动和表单验证中的最佳实践。还探讨了数组操作、对象属性管理和国际化显示技巧。
摘要由CSDN通过智能技术生成

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
})```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值