vue3进阶(一)——Promise.all请求多个接口的写法& 表单必填校验后再保存或提交 & @import url导入公共样式& module.exports定义对象和require导入js文件

本文介绍了在Vue3中如何使用Promise.all并发请求多个接口,并演示了表单必填项校验后保存或提交的功能,以及使用import和module.exports进行样式和模块导入的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

vue3进阶(一)——Promise.all请求多个接口的写法& 表单必填校验后再保存或提交 & @import url导入公共样式& module.exports定义对象和require导入js文件

写法一:表单必填校验后再保存或提交
1、vue详情/新增/编辑页面

needDetails.vue

<template>

  <div :class="route.query.type === 'view' ? 'box-main p-top58' : 'box-main'">
    <el-page-header class="page-header" :content="title" @back="goBack" />
    <el-form ref="formRef" label-width="128px" :model="formInline">
      <el-row>
        <el-col :span="6">
          <el-form-item label="需求名称:" prop="needName" :rules="{
            required: true,
            message: '请输入需求名称',
            trigger: 'change',
          }">
            <el-input v-model="formInline.needName" :disabled="route.query.type === 'view'" placeholder="点击输入框选择需求" />
          </el-form-item>
        </el-col>
        <el-col :span="6">
          <el-form-item label="需求编号:" prop="needCode">
            <el-input v-model="formInline.needCode" :disabled="route.query.type === 'view'" maxlength="100"
              placeholder="请输入" @input="(e) => (formInline.needCode = replaceCommonText(e))" />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  </div>
  <div style="padding-top: 22px">
    <div style="margin-bottom: 22px; font-size: 16px">变更信息:</div>
    <el-form ref="formRefTwo" label-width="128px" :model="formInline">
      <el-row>
        <el-col :span="6">
          <el-form-item label="原组别:" prop="oldGroupName" :rules="{
            required: true,
            message: '请输入',
            trigger: 'blur',
          }">
            <el-input v-model="formInline.oldGroupName" :disabled="route.query.type === 'view'" maxlength="100"
              placeholder="请输入" />
          </el-form-item>
        </el-col>
        <el-col :span="6">
          <el-form-item label="原技术领域:" prop="oldTechFieldName" :rules="[
            {
              validator: validateCommonText,
              trigger: ['blur', 'change'],
            },
          ]">
            <el-input v-model="formInline.oldTechFieldName" disabled placeholder="请输入" />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  </div>
  <div style="text-align: center" v-if="route.query.type !== 'view'">
    <el-button v-throttle="3000" style="margin: 5px 20px 0 0px" type="primary" @click="handleClick('save')">
      保存
    </el-button>
    <el-button v-throttle="3000" style="margin: 5px 20px 0 0px" type="primary" @click="handleClick('submit')">
      提交
    </el-button>
    <el-button plain style="margin: 5px 0px 0 0px" type="primary" @click="goBack">
      取消
    </el-button>
  </div>
</template>
<script setup>
import {
  saveDemandConvertGroup,
  updateDemandConvertData,
  batchGroupUpdateStatus,
} from '@/api/variousUnits/index.js'
import { replaceCommonText, validateCommonText } from '@src/utils/validate'
const formRef = ref()
const formRefTwo = ref(null)
const formInline = ref({
  needCode: '',
  needName: '',
  oldGroupName: '',
  oldTechFieldName: '',
})
const route = useRoute()
const router = useRouter()
const title = ref('需求添加')
if (route.query.type === 'view') {
  title.value = '需求管理详情'
} else if (route.query.type === 'edit') {
  title.value = '需求管理编辑'
}
// 返回列表
const goBack = async () => {
  if (JSON.parse(sessionStorage.getItem('manageZnIndex')) == '1') {
    sessionStorage.setItem('manageZnIndex', '1')
  }
  if (JSON.parse(sessionStorage.getItem('manageZnIndex')) == '2') {
    sessionStorage.setItem('manageZnIndex', '2')
  }
  router.push({
    path: '/comquart/variousUnits/comInplement',
  })
}
//点击按钮
const handleClick = async (item) => {
  // Promise.all 写法
  Promise.all([formRef.value.validate(), formRefTwo.value.validate()]).then(
    () => {
      method[item]()
    },
    () => { }
  )
}
const method = {
  // 方法-原生写法
  // 提交
  submit: function () {
    const ids = [formInline.value.id]
    const bizNames = [formInline.value.needName]
    const loading = ElLoading.service({
      lock: true,
      text: 'Loading',
      background: 'rgba(0, 0, 0, 0.7)',
    })
    batchGroupUpdateStatus({ ids, bizNames })
      .then((res) => {
        console.log(res)
        if (res.code === '00000') {
          ElMessage.success('提交成功')
          goBack()
        } else {
          ElMessage.error(res.message)
        }
      })
      .finally(() => {
        loading.close()
      })
  },
  // 保存
  save: function () {
    const require =
      route.query?.type === 'add'
        ? saveDemandConvertGroup
        : updateDemandConvertData
    const req = { ...formInline.value }
    const loading = ElLoading.service({
      lock: true,
      text: 'Loading',
      background: 'rgba(0, 0, 0, 0.7)',
    })
    require(req)
      .then((res) => {
        console.log(res)
        if (res.code === '00000') {
          ElMessage.success('保存成功')
          goBack()
        } else {
          ElMessage.error(res.message)
        }
      })
      .finally(() => {
        loading.close()
      })
  },
}
</script>
<style lang="scss" scoped>
@import url('../../style/main.scss');

.page-header {
  border-bottom: 20px solid #f8f8f8;

  :deep(.ym-page-header__header) {
    height: 40px;
    line-height: 40px;
  }
}
</style>
2、引用的公共样式

src\app\science\views\style\main.scss

.box-main {
  padding: 0px;
  background: #f8f8f8;
}
.p-top78 {
  padding: 78px 0 0;
}
3、引用的接口

src\app\science\api\variousUnits\index.js

import request from '@src/utils/request'
import { sciencePostUrl } from '@/config'

//指南编制-需求转租保存
export const saveDemandConvertGroup = (data) => {
  return request({
    url: `${sciencePostUrl}/demandConvert/saveDemandConvertGroup`,
    method: 'post',
    data,
  })
}

// 修改需求转租信息详情
export const updateDemandConvertData = (data) => {
  return request({
    url: `${sciencePostUrl}/demandConvert/updateDemandConvertData`,
    method: 'post',
    data,
  })
}

//指南编制-需求转租批量提交
export const batchGroupUpdateStatus = (data) => {
  return request({
    url: `${sciencePostUrl}/demandConvert/batchUpdateStatus`,
    method: 'post',
    data,
  })
}

src\app\science\config\index.js

/**
 * @description 4个子配置,vue/cli配置|通用配置|主题配置|网络配置导出
 *              config中的部分配置由vue.config.js读取,本质是node,故不可使用window等浏览器对象
 */
const cli = require('./cli.config')
const setting = require('./setting.config')
const theme = require('./theme.config')
const network = require('./net.config')
const prefixApi = require('./prefixApi.config')
module.exports = {
  ...cli,
  ...setting,
  ...theme,
  ...network,
  ...prefixApi,
}

src\app\science\config\prefixApi.config.js

module.exports = {
  planPostUrl: '/srbm-prj-plan-front/member',
  sciencePostUrl: '/srbm-prj-techprj-front/member',
  filePostUrl: '/srbm-bas-file-front/member',
  mgtPostUrl: '/srbm-mgt-gnlmgt-front/member',
  memPostUrl: '/inner/inner', //member
}
已经知道前端代码的统错误返回结果写法如下所示const add=()=&gt;{ formRef.value.validate((valid)=&gt;{ if(valid){//验证通过的话再新增 request.post(&#39;/category/add&#39;,data.form).then(res=&gt;{ if(res.code===&#39;200&#39;){ data.formVisible=false ElMessage.success(&#39;新增成功&#39;) load()//新增后重新加载最新的数据 }else{ ElMessage.error(res.msg) } }) } }) }重新给出对下面代码的修改&lt;script setup lang=&quot;ts&quot;&gt; import { ref, onMounted } from &#39;vue&#39; import axios from &#39;axios&#39; // 需确保已安装axios // 类型定义 interface CategoryEntity { id: number name: string // 假设字段名为name,根据实际接口调整 parentId: number | null children?: CategoryEntity[] } interface R&lt;T&gt; { code: number msg: string data: T } // 树形数据请求 const fetchCategoryTree = async (): Promise&lt;R&lt;CategoryEntity[]&gt;&gt; =&gt; { try { const response = await axios.get(&#39;/api/category/tree&#39;) return response.data } catch (error) { console.error(&#39;请求失败:&#39;, error) return { code: -1, msg: &#39;请求失败&#39;, data: [] } } } // 表格数据 const tableData = ref&lt;CategoryEntity[]&gt;([]) // 获取数据 const loadData = async () =&gt; { const res = await fetchCategoryTree() if (res.code === 0) { tableData.value = res.data } } // 初始化加载 onMounted(() =&gt; { loadData() }) // 修改操作示例 const handleEdit = (id: number) =&gt; { console.log(&#39;编辑ID:&#39;, id) // 这里添加实际编辑逻辑 } &lt;/script&gt; &lt;template&gt; &lt;div class=&quot;category-container&quot;&gt; &lt;el-table :data=&quot;tableData&quot; style=&quot;width: 100%&quot; row-key=&quot;id&quot; border default-expand-all :tree-props=&quot;{ children: &#39;children&#39;, hasChildren: &#39;hasChildren&#39; }&quot; &gt; &lt;el-table-column prop=&quot;id&quot; label=&quot;ID&quot; width=&quot;120&quot; /&gt; &lt;el-table-column prop=&quot;name&quot; label=&quot;分类名称&quot; /&gt; &lt;el-table-column prop=&quot;parentId&quot; label=&quot;父级ID&quot; width=&quot;120&quot; /&gt; &lt;el-table-column fixed=&quot;right&quot; header-align=&quot;center&quot; align=&quot;center&quot; width=&quot;150&quot; label=&quot;操作&quot; &gt; &lt;template #default=&quot;{ row }&quot;&gt; &lt;el-button type=&quot;primary&quot; link size=&quot;small&quot; @click=&quot;handleEdit(row.id)&quot; &gt; 编辑 &lt;/el-button&gt; &lt;/template&gt; &lt;/el-table-column&gt; &lt;/el-table&gt; &lt;/div&gt; &lt;/template&gt; &lt;style scoped&gt; .category-container { padding: 20px; background: #fff; border-radius: 4px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); } &lt;/style&gt;
03-22
&lt;think&gt;嗯,用户给了我前端代码,主要是关于Vue 3Element Plus的表格组件,还有请求后端数据的部分。他们希望根据提供的错误处理示例来修改现有代码,统错误返回结果的写法。首先,我需要仔细看看用户提供的示例代码是什么样的。 在示例中,用户使用了`formRef.value.validate`来进行表单验证,验证通过后发送请求,然后根据返回的`res.code`是否为&#39;200&#39;来决定显示成功错误消息。看起来他们的后端接口返回的code是字符串类型,而当前代码中的`R&lt;T&gt;`接口里code是number类型,这可能会导致判断错误,比如示例中的&#39;200&#39;是字符串,而代码里判断的是数字0。这可能是需要修改的第个点,把code的类型统。 接下来看用户提供的代码,`fetchCategoryTree`函数里,请求成功后直接返回`response.data`,但这里可能没有处理HTTP错误状态码,比如4xx5xx错误。虽然在try/catch里捕获了错误,但axios的错误处理可能需要更细致些,比如区分网络错误服务器返回的错误。此外,示例代码中使用了ElMessage来显示成功错误消息,但当前代码在请求失败时只是console.error,没有用户反馈,应该添加ElMessage提示。 然后看`loadData`函数,这里判断`res.code === 0`,但示例中是判断&#39;200&#39;,这明显不致。需要确认后端的实际返回结构,是code为0还是200,者其他值。假设示例中的正确code是200,但当前代码中判断的是0,这会导致逻辑错误,数据无法正确加载。所以需要调整code的判断条件,可能要将code改为字符串类型,者数字类型,根据实际情况调整。 另外,在错误处理部分,示例代码返回了`{ code: -1, msg: &#39;请求失败&#39;, data: [] }`,但可能后端在HTTP错误时(比如500)会返回不同的code,这里可能需要更详细的错误信息。者在axios的catch块中,解析error对象,提取服务器返回的错误信息,而不是统返回code为-1。 还有,示例代码中的成功提示是ElMessage.success,而当前代码在成功时没有提示,是否需要添加?用户可能希望在加载数据成功后也有提示,但原示例中的新增成功才有提示,所以可能不需要。但需要根据用户的实际需求来决定。 接下来,考虑代码的改进点: 1.错误处理,使用ElMessage显示错误信息。 2. 调整code的类型判断条件,与后端致。 3. 在axios请求中处理HTTP错误,比如状态码非200的情况。 4. 可能需要在请求失败时返回更详细的错误信息,而不是固定的msg。 具体到代码修改: - 在`fetchCategoryTree`中,axios.get可能会抛出错误,比如网络问题HTTP错误状态码。在catch块中,应该判断error是否是axios的错误实例,然后提取服务器返回的msg,者使用默认消息。例如: ```typescript catch (error) { let message = &#39;请求失败&#39;; if (axios.isAxiosError(error)) { message = error.response?.data?.msg || error.message || message; } ElMessage.error(message); return { code: -1, msg: message, data: [] }; } ``` 这样能更准确地显示后端返回的错误信息。 - 修改`R&lt;T&gt;`接口中的code为string类型,如果后端返回的是字符串的话。者根据实际情况调整,比如示例中的code是&#39;200&#39;,而当前代码中是0,这里可能存在矛盾,需要统。 假设后端返回的code是数字,比如200代表成功,那么示例中的判断应该是res.code === 200,但原示例中使用的是&#39;200&#39;,这可能是用户的错误,需要确认。如果后端确实返回字符串,那么接口需要调整。 假设用户示例中的code === &#39;200&#39;是正确的,那么当前代码中的`R&lt;T&gt;`的code应为string类型,而`fetchCategoryTree`中判断res.code === &#39;200&#39;。但用户当前代码中的`loadData`判断的是res.code === 0,这明显不致,需要修正。 另外,在示例代码中,成功时执行`load()`重新加载数据,当前代码的`loadData`可能也需要在成功时重新加载,但当前逻辑是onMounted时调用loadData,可能在新增成功后需要手动调用loadData,但用户的示例代码中已经这样做了。 此外,当前的`handleEdit`函数只是个示例,可能需要补充实际的编辑逻辑,比如打开对话框,填充表单等,但用户可能只关注错误处理部分,所以暂时可以不修改。 总结需要修改的部分: 1. 调整`R&lt;T&gt;`接口的code类型,与后端致。 2. 在fetchCategoryTree中添加错误处理,使用ElMessage显示错误信息。 3. 在loadData中根据正确的code判断是否成功,并处理数据。 4.错误消息的显示方式,如成功失败都使用ElMessage。 现在,根据这些分析,编写修改后的代码,并解释每步的改动原因。&lt;/think&gt;根据你提供的错误处理示例,我将从以下几个方面对代码进行优化修改: 请求错误处理增强版 ```typescript // 修改后的请求方法(包含三层错误处理) const fetchCategoryTree = async (): Promise&lt;R&lt;CategoryEntity[]&gt;&gt; =&gt; { try { const response = await axios.get&lt;R&lt;CategoryEntity[]&gt;&gt;(&#39;/api/category/tree&#39;) // HTTP 状态码处理(第层) if (response.status !== 200) { ElMessage.error(`请求异常(状态码:${response.status})`) return { code: -1, msg: &#39;HTTP协议错误&#39;, data: [] } } // 业务状态码处理(第二层) if (response.data.code !== 0) { // 根据你的接口文档调整成功码 ElMessage.error(response.data.msg || &#39;业务处理失败&#39;) return response.data // 保持错误数据传递 } return response.data } catch (error) { // 异常处理(第三层) let errorMsg = &#39;网络请求失败&#39; if (axios.isAxiosError(error)) { errorMsg = error.response?.data?.msg || error.message } ElMessage.error(errorMsg) return { code: -1, msg: errorMsg, data: [] } } } ``` 二、加载逻辑优化 ```typescript const loading = ref(false) // 新增加载状态 const loadData = async () =&gt; { try { loading.value = true const res = await fetchCategoryTree() // 类型安全校验 if (res.code === 0 &amp;&amp; Array.isArray(res.data)) { tableData.value = res.data.map(item =&gt; ({ ...item, children: item.children || [] // 确保children始终为数组 })) } } finally { loading.value = false } } ``` 三、表格状态增强 ```vue &lt;el-table :data=&quot;tableData&quot; v-loading=&quot;loading&quot; :element-loading-text=&quot;&#39;数据加载中...&#39;&quot; :element-loading-background=&quot;&#39;rgba(0, 0, 0, 0.8)&#39;&quot; &lt;!-- 保持原有其他属性 --&gt; &gt; &lt;!-- 列定义保持不变 --&gt; &lt;/el-table&gt; ``` 修改要点说明: 1. 三层错误处理体系: - HTTP协议层:处理401/404/500等状态码 - 业务逻辑层:处理接口定义的业务错误码 - 网络异常层:处理断网、超时等异常 2. 类型安全强化: - 明确的axios响应泛型类型`axios.get&lt;R&lt;CategoryEntity[]&gt;&gt;` - 数据转换时添加Array.isArray类型保护 - 初始化children为空数组避免undefined 3. 用户体验优化: - 添加loading状态反馈 - 统错误消息展示样式 - 保持与示例代码致的ElMessage使用方式 4. 可维护性提升: - 分离网络错误与业务错误处理 - 保留完整的错误传播链 - 添加详细的类型注释 建议补充的优化点: ```typescript // 在全局axios配置中添加错误拦截器(推荐在单独文件中配置) axios.interceptors.response.use( response =&gt; response, error =&gt; { if (!window.navigator.onLine) { error.message = &#39;网络连接已断开&#39; } return Promise.reject(error) } ) ``` 这种修改方案实现了: 1. 错误处理分层明确 2. TypeScript类型安全 3. 用户体验致性 4. 代码可维护性 5. 防御性编程 与示例代码保持致的错误处理风格,同时增强了类型安全错误处理粒度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值