vue数据重置

前言

大家在开发后台管理系统的过程中,一定会遇到一个表格的条件查询重置功能吧,如果说查询条件少,重置起来还算是比较简单,如果元素特别多呢,那玩意写起来可遭老罪喽,那今天就给大家整一个如何快速重置数据的功能吧

实现方式一

实现方式一较为简单,就不上代码了,大概就是创建两个一样的数据,修改的是其中一个,然后需要重置的时候,将另一个定义的数据深拷贝给被修改的数据,就可以实现了

实现方式二

基本的思路跟实现方式一是一样的,只不过稍微处理了一下,封装成一个hooks,这样只需要自定义数据的时候执行这个函数即可; 上代码

import { reactive, isRef } from 'vue';

// 深拷贝函数,避免使用 JSON.parse(JSON.stringify) 的局限性
const deepClone = (obj: any) => {
  return JSON.parse(JSON.stringify(obj));
  // 或者使用更健壮的实现,比如 lodash 的 cloneDeep
  // return _.cloneDeep(obj);
};

export const useReset = <T extends object>(value: T) => {
  // 如果 value 是 ref,则获取其值
  const state = isRef(value)
    ? reactive(deepClone(value.value))
    : reactive(deepClone(value));

  const reset = (key?: keyof T, specificResetValue?: any) => {
    // 如果指定了 key,重置该属性
    if (key) {
      if (specificResetValue !== undefined) {
        // 如果提供了 specificResetValue,重置为这个值
        state[key] = specificResetValue;
      } else if (key in value) {
        // 否则重置为初始值
        state[key] = deepClone((value as any)[key]);
      }
    } else {
      // 如果没有指定 key,重置为初始值
      Object.assign(state, deepClone(value));
    }

    // 删除 state 中不再存在于 value 的属性
    Object.keys(state).forEach((k) => {
      if (!(k in value)) {
        delete state[k];
      }
    });
  };

  return { state, reset };
};

注意:深拷贝建议使用已经lodash或者其他比较完善的深拷贝方法,这里只是简单处理,知道原理即可
使用方式:

 <el-button @click="reset('form')">重置</el-button>
const { state, reset } = useReset({
  form: { title: '', typeId: '', type: '', isAppear: '' },
  formList: [
    {
      type: 'input',
      label: '标题',
      value: 'title',
      attrs: {
        placeholder: '请输入标题',
        width: '120',
      },
      // formLabel: '标题',
      formItemAttrs: {
        prop: 'title',
        label: '标题',
        labelWidth: '50px',
      },
    },
    {
      type: 'select',
      label: '分类',
      value: 'typeId',
      attrs: {
        placeholder: '请输入分类',
        width: '120',
        style: 'width: 120px',
      },

      formItemAttrs: {
        prop: 'typeId',
        label: '分类',
      },
      selectlabel: 'type',
      Keyvalue: 'id',
      list: [],
      childrenComponent: {
        type: 'option',
      },
    },
    {
      type: 'select',
      label: '类型',
      value: 'type',
      attrs: {
        placeholder: '请选择类型',
        width: '120',
        style: 'width: 120px',
      },

      formItemAttrs: {
        prop: 'type',
        label: '类型',
      },
      selectlabel: 'label',
      Keyvalue: 'value',
      list: [
        { value: 1, label: '原创' },
        { value: 2, label: '转载' },
      ],
      childrenComponent: {
        type: 'option',
      },
    },
    {
      type: 'select',
      label: '状态',
      value: 'isAppear',
      attrs: {
        placeholder: '请选择状态',
        width: '120',
        style: 'width: 120px',
      },

      formItemAttrs: {
        prop: 'type',
        label: '状态',
      },
      selectlabel: 'label',
      Keyvalue: 'value',
      list: [
        { value: 1, label: '可见' },
        { value: 3, label: '草稿' },
      ],
      childrenComponent: {
        type: 'option',
      },
    },
  ],
});

上面的实现可以只对某一个属性进行重置,案例

<template>
  <div style="height: 100vh">
    <kt-form v-model="state" :formAttrs="formAttrs"></kt-form>
    <el-button @click="see" type="primary">查询</el-button>
    <el-button @click="reset('form')">重置</el-button>
    <!-- <el-button type="primary" @click="add">添加</el-button> -->
    <kt-table
      :column="articleColumn"
      :default-sort="{ prop: 'date', order: 'descending' }"
      :tableData
      @selection-change="handleSelectionChange"
      :page-sizes="[10, 20, 30, 40]"
      layout="total, sizes, prev, pager, next, jumper"
      v-model="page"
      :total
      :tableColumnAttrs="tableColumnAttrs"
      @confirm="confirm"
      @handleClick="handleClick"
    >
      <template #tags="scope">
        <el-tag
          v-for="(item, index) in scope.row.tags"
          :key="index"
          :type="tagType[index % tagType.length]"
          >{{ item }}</el-tag
        >
      </template>
      <template #isAppear="scope">
        <el-select
          v-model="scope.row.isAppear"
          style="width: 120px"
          @change="(value) => changeIsAppear(value, scope.row.id)"
        >
          <el-option
            v-for="item in isAppearList"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          ></el-option>
        </el-select>
      </template>
      <template #type="scope">
        <el-tag :type="appear(scope.row.type)">
          {{ scope.row.type === '1' ? '原创' : '转载' }}</el-tag
        >
      </template>
      <template #isTop="scope">
        <el-switch
          v-model="scope.row.isTop"
          active-value="1"
          inactive-value="2"
          @change="(value) => changeIsAppear(value, scope.row.id)"
        />
      </template>
      <template #typeId="scope">
        {{ format(scope.row.typeId) }}
      </template>
    </kt-table>
    {{ state.id }}
  </div>
</template>
<script setup lang="ts">
import { articleColumn } from '@/common/column';
import { list, update, del } from '@/request/article';
import { useReset } from '@/hooks/useResert';
import { ElMessage } from 'element-plus';
import { useTypelist } from '@/hooks/useTypelist';
import router from '@/router';
import { useInit } from '@/store/index.ts';
const init = useInit();
const typeList = ref<any[]>([]);

import 'element-plus/theme-chalk/el-message.css';
const formAttrs = {
  inline: true,
  labelWidth: '50px',
};

interface IArticle {
  id: number;
  [key: string]: any;
}
let total = 0;
const { state, reset } = useReset({
  form: { title: '', typeId: '', type: '', isAppear: '' },
  formList: [
    {
      type: 'input',
      label: '标题',
      value: 'title',
      attrs: {
        placeholder: '请输入标题',
        width: '120',
      },
      // formLabel: '标题',
      formItemAttrs: {
        prop: 'title',
        label: '标题',
        labelWidth: '50px',
      },
    },
    {
      type: 'select',
      label: '分类',
      value: 'typeId',
      attrs: {
        placeholder: '请输入分类',
        width: '120',
        style: 'width: 120px',
      },

      formItemAttrs: {
        prop: 'typeId',
        label: '分类',
      },
      selectlabel: 'type',
      Keyvalue: 'id',
      list: [],
      childrenComponent: {
        type: 'option',
      },
    },
    {
      type: 'select',
      label: '类型',
      value: 'type',
      attrs: {
        placeholder: '请选择类型',
        width: '120',
        style: 'width: 120px',
      },

      formItemAttrs: {
        prop: 'type',
        label: '类型',
      },
      selectlabel: 'label',
      Keyvalue: 'value',
      list: [
        { value: 1, label: '原创' },
        { value: 2, label: '转载' },
      ],
      childrenComponent: {
        type: 'option',
      },
    },
    {
      type: 'select',
      label: '状态',
      value: 'isAppear',
      attrs: {
        placeholder: '请选择状态',
        width: '120',
        style: 'width: 120px',
      },

      formItemAttrs: {
        prop: 'type',
        label: '状态',
      },
      selectlabel: 'label',
      Keyvalue: 'value',
      list: [
        { value: 1, label: '可见' },
        { value: 3, label: '草稿' },
      ],
      childrenComponent: {
        type: 'option',
      },
    },
  ],
});

const tagType: any = ['primary', 'success', 'info', 'warning', 'danger'];
const see = () => {
  // console.log(forms.form);
  // reset(state.form);
  console.log(state);
  getList();
};
const tableColumnAttrs = {
  fixed: 'right',
  align: 'center',
  minWidth: '120',
};

const tableData = ref([]);
const page = ref({
  currentPage: 1,
  currentSize: 10,
});

const handleSelectionChange = (val: any) => {
  console.log(val);
};

const isAppearList = [
  {
    value: '1',
    label: '可见',
  },

  {
    value: '3',
    label: '草稿',
  },
];
const format = (id: string | number) => {
  // console.log(typeList, 'typeList');
  return typeList.value.find((item: any) => item.id === id)?.type || '';
};
const updateTable = async (id: number) => {
  const result: any = tableData.value.find((item: IArticle) => item.id === id);
  if (!result) return;
  const index: number = tableData.value.findIndex((item: IArticle) => item.id === id);
  const json: any = { ...result };
  json.tags = json.tags.join(',');
  // 调用更新
  const res = await update(json);
  if (res.status) {
    ElMessage.success(res.message);
    histList[index] = tableData.value[index] as IArticle;
  } else {
    ElMessage.error(res.message);
    // 还原原来的数据
    if (index !== -1) {
      (tableData.value[index] as IArticle) = histList[index];
    }
  }
};
// isAppear
// 切换状态
const changeIsAppear = async (_val: string | number | boolean, id: number) => {
  await updateTable(id);
};
const appear = (isAppear: string) => {
  switch (isAppear) {
    case '1':
      return tagType[1];
    case '2':
      return tagType[0];
    case '3':
      return tagType[3];
    default:
      return tagType[3];
  }
};
let histList: IArticle[] = [];
const getList = async () => {
  const json: any = { ...page.value, ...state.form };
  json.page = page.value.currentPage;
  json.pageSize = page.value.currentSize;
  const res = await list({ ...json });
  res.data.articles.forEach((item: any) => {
    item.tags = item.tags.split(',');
  });
  tableData.value = res.data.articles;
  total = res.data.totalCount;
  histList = JSON.parse(JSON.stringify(res.data.articles));
};

// 删除单个
const confirm = async (row: IArticle) => {
  const res: any = await del(row.id);
  if (res.status) {
    ElMessage.success(res.message);
    getList();
  } else {
    ElMessage.error(res.message);
  }
};
// 编辑
const handleClick = (row: IArticle) => {
  init.changeCurrentTab('articleAdd', '1-2');
  // query传参跳转
  router.push({
    path: '/articleAdd',
    query: {
      id: row.id,
    },
  });
};
watch(
  [() => page.value.currentPage, () => page.value.currentSize],
  () => {
    getList();
  },
  { immediate: true },
);
onMounted(async () => {
  const { data } = await useTypelist();

  typeList.value = data.value;
  state.formList[1].list = data.value;
});
// 查询列表
</script>
<style lang="scss" scoped></style>


上面是一个页面,展示

image
其中,分类,类型和状态的下拉数据通过接口获取的,所以,当数据重置的时候,我是不能formList里面的数据,否则会导致下拉列表为空,这时候,只需要调用reset,然后传入需要重置的的数据,这里需要重置的是form,所以重置调用reset(‘form’)
image

总结

以上就是通过函数的方式实现数据重置,本质上还是通过一个新的数据对老数据进行覆盖,如果有问题欢迎提出

<think>好的,用户之前问过关于在Ant Design Vue的选择组件中实时拼接逗号的问题,现在他们遇到了重置表单时thirdDeptCode的值没有被清空的情况。我需要先理解这个问题的具体表现。 用户可能在使用表单重置功能时,发现thirdDeptCode字段没有正确清空。这可能是因为他们使用的重置方法没有处理到该字段,或者因为数据绑定方式导致的问题。之前的解决方案中,用户使用了两个变量:selectArray(数组)和queryParam.thirdDeptCode(字符串),这可能导致了数据同步的问题。 接下来,我需要考虑用户可能使用的重置方式。通常表单重置可能通过调用表单实例的resetFields方法,或者手动将表单数据重置为初始值。如果resetFields没有生效,可能是因为表单项没有被正确注册,或者初始值本身不为空。此外,如果用户手动重置queryParam.thirdDeptCode,但没有同时清空selectArray,那么组件显示的值可能不会更新,因为selectArray是绑定到选择组件的。 可能的解决方案包括检查表单注册、确保重置时同时清空两个变量、使用Vue的响应式方法等。还需要提醒用户注意数据同步的问题,比如在重置时不仅要处理queryParam,还要处理selectArray,因为这两个变量是双向绑定的。此外,如果使用了watch来同步数据,可能需要调整监听的逻辑,避免在重置时触发不必要的更新。 最后,用户可能需要一个具体的代码示例,展示如何在重置时正确清空所有相关变量,并确保表单组件正确更新。同时需要解释不同重置方法的适用场景,以及如何避免数据不同步的问题。</think>$$问题定位与解决方案$$ 出现重置未清空值的问题通常由以下原因导致: $$数据同步关系图$$ ``` 表单重置操作 ├─ 方式1:调用表单实例resetFields() │ └─ 未生效原因:字段未正确注册到form实例 ├─ 方式2:手动重置queryParam对象 │ └─ 未生效原因:selectArray未同步清空 └─ 方式3:直接操作selectArray └─ 未生效原因:queryParam.thirdDeptCode未更新 ``` $$推荐解决方案$$ ```javascript{5-6,9-10,14} // 方案一:统一重置入口 const formRef = ref() // 重置方法(推荐) const handleReset = () => { // 清空业务参数 queryParam.thirdDeptCode = '' // 清空组件绑定值 selectArray.value = [] // 调用Antd表单重置 formRef.value?.resetFields() } // 方案二:深度监听(适用于复杂场景) watch( () => queryParam.thirdDeptCode, (newVal) => { if (!newVal) selectArray.value = [] } ) ``` $$常见问题排查表$$ | 现象 | 检查点 | 解决方法 | |----------------------|-------------------------------|--------------------------------| | 点击重置后UI未清空 | 1. selectArray是否被清空 | 添加`selectArray.value = []` | | 控制台数据未清空 | 2. queryParam是否保持响应式 | 使用`reactive()`包裹数据对象 | | 部分重置成功 | 3. 表单字段注册是否完整 | 检查`<a-form :model="queryParam">`绑定 | | 重置后无法再次选择 | 4. 选项数据源是否被意外修改 | 冻结选项数据:`Object.freeze(deptOptions)` | $$增强型重置方案$$ ```javascript{3-5,8} // 带初始值的可靠重置 const initFormData = { thirdDeptCode: '' } // 创建响应式数据时保留初始值副本 const queryParam = reactive({ ...initFormData }) // 强化重置方法 const handleReliableReset = () => { Object.assign(queryParam, initFormData) // 重置业务参数 selectArray.value = [] // 清空UI绑定值 nextTick(() => formRef.value?.clearValidate()) // 清除校验状态 } ``` $$Ant Design表单重置原理$$ ``` resetFields()工作原理: 1. 读取form组件的initialValue 2. 将当前值重置为initialValue 3. 清除校验状态 关键配置: <a-form :model="queryParam" ref="formRef" :initial-values="initFormData" <!-- 必须与model结构一致 --> > ``` $$最佳实践建议$$ 1. **双重保险策略**:同时操作UI组件和业务数据 ```javascript const handleReset = async () => { await formRef.value.resetFields() selectArray.value = [] } ``` 2. **初始值标准化**: ```javascript{2-4} // 初始化时显式设置默认值 onMounted(() => { formRef.value?.setFieldsValue(initFormData) selectArray.value = [] }) ``` 3. **防御性编程**: ```javascript // 处理null/undefined情况 selectArray.value = (queryParam.thirdDeptCode || '') .split(',') .filter(Boolean) ``` 4. **状态快照**(适用于需要撤销操作的场景): ```javascript let formSnapshot = null const makeSnapshot = () => { formSnapshot = JSON.parse(JSON.stringify(queryParam)) } const restoreSnapshot = () => { Object.assign(queryParam, formSnapshot) selectArray.value = formSnapshot.thirdDeptCode.split(',') } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值