FreeChilly 2022-03-25 14:25 采纳率: 50%
浏览 392
已结题

vue3input输入防抖校验问题

https://github.com/zhou62396272/bucketName
这是我写的简单的模板,不嫌麻烦的可以跑一下项目帮我解决一下,先谢谢各位了!!🙏

问题就是在输入框里 快速输入后停止时,触发了validator的校验提示,但是页面没有更新
如果是慢慢的 一个一个输入,是可以正常触发,并显示校验的

vue3 + antd2.2

<template>
  <div class="width">
    <a-form :model="bucketInfo">
      <a-form-item
        label="Bucket名称"
        name="bucketName"
        :rules="rule.bucketNameRules()"
      >
        <a-input style="width: 500px;" v-model:value="bucketInfo.bucketName" :maxlength="63" placeholder="Bucket名称" />
      </a-form-item>
    </a-form>
  </div>
</template>

<script setup>
// 一个一个 慢慢输入 => 正常提示
// 快速输入后停止时,如何能正常触发校验提示???

import "ant-design-vue/dist/antd.css";
import { reactive } from "vue";
import axios from "axios";

const bucketInfo = reactive({
  bucketName: ''
})

const abortPromise = (promise1) => {
  let abort;
  const promise2 = new Promise((resolve, reject) => {
    abort = reject;
  });
  const p = Promise.race([promise1, promise2]);
  p.abort = abort;
  return p;
};

const debouncePromise = (success, fail, time) => {
  let promise;
  return function (...rest) {
    if (promise && typeof promise.abort === "function") {
      promise.abort();
    }
    const timeoutPromise = new Promise((resolve) => {
      setTimeout(() => {
        resolve(undefined); //个人觉得就是每次输入都会立刻resolve,所以页面会来不及更新
      }, time);
    });
    promise = abortPromise(timeoutPromise);
    return promise.then(
      () => {
        return success(...rest);
      },
      () => {
        return fail(...rest);
      }
    );
  };
};

const fail = () => {
  console.log("由于防抖中断了第一次的请求");
  return Promise.resolve(); // 忽视它暂时是正确的
};

const success = (rule, value) => {
  console.log("请求后台接口");
  const reg = /^(?!(-|[-a-z0-9]*--|[-a-z0-9]*-$))[-a-z0-9]*[-a-z0-9]*$/;
  if (value.length < 1) {
    return Promise.reject("名称不能为空");
  }
  if (value.length < 3 || value.length > 63) {
    return Promise.reject("请输入 3~63 个字符");
  } else if (!reg.test(value)) {
    return Promise.reject("只允许小写字母、数字、短横线(-),且不能以短横线开头或结尾");
  }
  // 调用接口查询是否重复
  axios
    .get(
      "https://www.fastmock.site/mock/a535d266440f87553f2748030e9505cb/starship-ss3/api/check",
      value
    )
    .then((res) => {
      console.log(res.data);
    });
};

const check = debouncePromise(success, fail, 200);

const rule = {
  bucketNameRules() {
    return { validator: check, trigger: "change", required: true };
  },
};
</script>


  • 写回答

4条回答 默认 最新

  • 观察蚂蚁的人 2022-03-25 21:53
    关注

    在题主的代码基础上改了两个地方:1、逻辑简化,去掉了abortPromise;2、加上了对TimeOut的请求限制,避免页面上同时存在很多的TImeOut;我试了一下这个是可以快速输入,页面也跟着更新了,连续输入的时候,会等停下来再校验。

    <template>
      <div class="width">
        <a-form :model="bucketInfo">
          <a-form-item
            label="Bucket名称"
            name="bucketName"
            :rules="rule.bucketNameRules()"
          >
            <a-input style="width: 500px;" v-model:value="bucketInfo.bucketName" :maxlength="63" placeholder="Bucket名称" />
          </a-form-item>
        </a-form>
      </div>
    </template>
    
    <script setup>
    import "ant-design-vue/dist/antd.css";
    import { reactive } from "vue";
    import axios from "axios";
    
    const bucketInfo = reactive({
      bucketName: ''
    });
    
    const timerArr = [];  //记录定时器
    
    const timeCls =()=>{
      timerArr.forEach(item=>{clearTimeout(item);});
      timerArr.splice(0,timerArr.length);
    }
    
    const debouncePromise = (success, time) => {
      return function (...rest) {
        const timeoutPromise = new Promise((resolve) => {
    
          //如果定时器已开启先清空
          if(timerArr.length>0){timeCls();}
     
          let timer=setTimeout(() => {
            timeCls();
            resolve(undefined); 
          }, time);
          timerArr.push(timer);
          // console.log("中断请求");
        });
        
        return timeoutPromise.then(
          () => {
            return success(...rest);
          }
        );
      };
    };
    
    const success = (rule, value) => {
      // console.log("请求后台接口");
      const reg = /^(?!(-|[-a-z0-9]*--|[-a-z0-9]*-$))[-a-z0-9]*[-a-z0-9]*$/;
      if (value.length < 1) {
        return Promise.reject("名称不能为空");
      }
      if (value.length < 3 || value.length > 63) {
        return Promise.reject("请输入 3~63 个字符");
      } else if (!reg.test(value)) {
        return Promise.reject("只允许小写字母、数字、短横线(-),且不能以短横线开头或结尾");
      }
      // 调用接口查询是否重复
      axios
        .get(
          "https://www.fastmock.site/mock/a535d266440f87553f2748030e9505cb/starship-ss3/api/check",
          value
        )
        .then((res) => {
          console.log(res.data);
        });
    };
    
    const check = debouncePromise(success, 200); 
    
    const rule = {
      bucketNameRules() {
        return { validator: check, trigger: "change", required: true };
      },
    };
    </script>
    
    <style>
    #app {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    .width {
      width: 100%;
      display: flex;
      justify-content: center;
    }
    .w500 {
      width: 500px;
    }
    </style>
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 4月5日
  • 已采纳回答 3月28日
  • 创建了问题 3月25日

悬赏问题

  • ¥15 乘性高斯噪声在深度学习网络中的应用
  • ¥15 运筹学排序问题中的在线排序
  • ¥15 关于docker部署flink集成hadoop的yarn,请教个问题 flink启动yarn-session.sh连不上hadoop,这个整了好几天一直不行,求帮忙看一下怎么解决
  • ¥30 求一段fortran代码用IVF编译运行的结果
  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛
  • ¥30 python代码,帮调试,帮帮忙吧