Vue3项目中弹窗数据不回显问题

221 阅读3分钟

需求:Vue3项目+Element Plus项目,点击table列表中“修改”按钮,弹窗回显该行数据。

问题:点击“修改”按钮,弹窗没有回显改行数据。

原代码展示

<template>
  <div class="app-container">
    <!-- 条件查询 -->
    <el-form :model="queryParams" ref="queryRef" v-show="showSearch" :inline="true" label-width="68px">
      <el-form-item label="Key" prop="key">
        <el-input v-model="queryParams.key" placeholder="请输入cookie/token的Key" clearable style="width: 240px"
          @keyup.enter="handleQuery" />
      </el-form-item>
      <el-form-item label="Name" prop="name">
        <el-input v-model="queryParams.name" placeholder="请输入Name" clearable style="width: 240px"
          @keyup.enter="handleQuery" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form> <!-- 表格数据 -->
    <el-table v-loading="loading" :data="cookiesList" @selection-change="handleSelectionChange" ref="multipleTable">
      <el-table-column type="selection" width="55"></el-table-column>
      <el-table-column label="ID" prop="id" width="80" align="center" />
      <el-table-column label="类型" prop="type" :show-overflow-tooltip="true" width="120" align="center" />
      <el-table-column label="Name" prop="name" :show-overflow-tooltip="true" width="140" align="center" />
      <el-table-column label="Key" prop="key" :show-overflow-tooltip="true" width="160" align="center" />
      <el-table-column label="Value" prop="value" :show-overflow-tooltip="true" min-width="200"> <template
          #default="scope"> <span class="value-text">{{ scope.row.value }}</span>
        </template>
      </el-table-column>
      <el-table-column label="创建时间" align="center" prop="create_time" width="200"> <template #default="scope">
          <span>{{ dayjs(scope.row.create_time).format('YYYY-MM-DD HH:mm:ss') }}</span>
        </template>
      </el-table-column> <!-- 操作列-修改 -->
      <el-table-column label="操作" align="center" width="120"> <template #default="scope">
          <el-button type="text" @click="handleEdit(scope.row)">修改</el-button>
        </template>
      </el-table-column>
    </el-table> <!-- 分页 -->
    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
      v-model:limit="queryParams.pageSize" @pagination="getList" /> <!-- 修改Value弹窗 -->
    <el-dialog v-model="editDialogVisible" title="修改Cookies Value" :width="500" @close="resetEditDialog">
      <el-form ref="editForm" :model="editForm" :rules="editRules" label-width="80px">
        <el-form-item label="ID" prop="id">
          <el-input v-model="editForm.id" disabled />
        </el-form-item>
        <el-form-item label="Key" prop="key">
          <el-input v-model="editForm.key" disabled />
        </el-form-item>
        <el-form-item label="Value" prop="value">
          <el-input v-model="editForm.value" type="textarea" :rows="6" placeholder="请输入修改后的Value" maxlength="10000"
            show-word-limit />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="resetEditDialog">取消</el-button>
        <el-button type="primary" @click="confirmEdit">确认修改</el-button>
      </template>
    </el-dialog>
  </div>
</template>
<script setup name="CookiesManagement">
  //引入自己的接口路径
import dayjs from 'dayjs';
import { ref, reactive, toRefs, getCurrentInstance } from 'vue';
const { proxy } = getCurrentInstance();
const cookiesList = ref([]);
const loading = ref(true);
const showSearch = ref(true);
const total = ref(0); // 用于存储选中的行数据 
const multipleSelection = ref([]); // 表格的ref,用于调用表格的方法 
const multipleTable = ref(null); // 查询参数 
const data = reactive({ queryParams: { pageNum: 1, pageSize: 10, key: undefined, name: undefined, }, });
const { queryParams } = toRefs(data); // 修改弹窗相关 
const editDialogVisible = ref(false);
const editForm = reactive({ id: '', key: '', value: '' });
const editRules = { value: [{ required: true, message: '请输入修改后的Value', trigger: 'blur' }, { max: 10000, message: 'Value不能超过10000个字符', trigger: 'blur' }] };
 /** 获取Cookies列表 */ function getList() {
    loading.value = true;
    const params = { ...queryParams.value };
    getCookiesList(params).then(response => { cookiesList.value = response.data.data; total.value = response.data.total; loading.value = false; }).catch(error => { loading.value = false; proxy.$message.error('获取Cookies列表失败,请稍后重试'); console.error('获取列表失败:', error); });
}
 /** 搜索按钮操作 */ 
 function handleQuery() { queryParams.value.pageNum = 1; getList(); }
  /** 重置按钮操作 */ 
  function resetQuery() { proxy.resetForm("queryRef"); handleQuery(); }
   /** 选择项变化时触发 */
    function handleSelectionChange(val) { multipleSelection.value = val; } 
    /** 打开修改弹窗 */
     function handleEdit(row) { 
     // 赋值当前行数据到修改表单 
     editForm.id = row.id; editForm.key = row.key; editForm.value = row.value; editDialogVisible.value = true; }
      /** 确认修改Value */ 
      function confirmEdit() { proxy.$refs.editForm.validate(async (valid) => { if (valid) { updateCookiesValue(editForm.id, editForm.value) .then(() => { proxy.$message.success('Value修改成功'); editDialogVisible.value = false; getList().catch(err => { proxy.$message.error('修改成功,但刷新列表失败'); console.error('列表刷新失败:', err); }); }) .catch((error) => { 
        // 捕获接口调用失败的错误 
        proxy.$message.error('修改时发生错误,请稍后重试'); console.error('修改失败:', error); }); } }); } 
        /** 重置修改弹窗 */ 
        function resetEditDialog() { editForm.id = ''; editForm.key = ''; editForm.value = ''; proxy.resetForm('editForm'); editDialogVisible.value = false; } 
        // 初始加载列表 
        getList(); 
</script>
<style scoped>
  .app-container {
    padding: 20px;
  }

  .value-text {
    color: #606266;
    word-break: break-all;
  }
</style>

问题原因: 获取当前实例的proxy方式在 Vue3 setup 中已失效,导致resetEditDialog函数执行时错误调用proxy.resetForm,清空了刚赋值的表单数据。

具体分析:在 Vue3 的<script setup>语法中,getCurrentInstance().proxy并非推荐且稳定的用法,尤其在最新版本的 Vue 或 Element Plus 中,该方式可能无法正确获取到组件实例,进而导致:

  1. resetEditDialog函数异常:每次打开弹窗前,若误触发resetEditDialog(如弹窗关闭时),会通过无效的proxy调用resetForm,但实际可能未正确重置表单,或在某些场景下反向清空已赋值的editForm
  2. 数据赋值被覆盖:即使handleEdit中给editForm赋了值,但后续若因proxy失效导致的表单重置逻辑异常,会覆盖已赋值的idkeyvalue,最终表现为弹窗无数据。

解决方案:

1.替换proxy,使用 Vue3 推荐的表单操作方式

<script setup>中,无需通过getCurrentInstance获取proxy,直接使用ref获取表单实例,调用resetFields方法(Element Plus 表单的标准重置方法)。

  1. 调整弹窗关闭时的重置逻辑 为避免关闭弹窗时立刻清空数据,可将resetEditDialog的清空逻辑延迟到弹窗打开前执行,而非关闭时

修改后的完整代码: