https://github.com/zhou62396272/bucketName
这是我写的简单的模版案例,不嫌麻烦的可以跑一下项目试试帮我解决一下,🙏谢谢了!!
因为要求是输入即校验,需要调用接口,所以需要防抖
因为callback已废除,必须以Promise的形式才能触发validator,一般的debounce不能满足返回Promise的需求
现在的问题是:输入框不停输入时,以下代码防抖效果有了
但是因为每次输入都会把之前的那一次Promise取消掉,于是当我快速输入时,最后一次输入停了之后,其实是触发validator提示了,但是因为之前不停的在取消,所以页面来不及渲染,导致页面没有任何提示
如果是一个一个慢慢输入的话是能正常显示校验的
请问有什么解决方法吗
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)
}, time)
})
promise = abortPromise(timeoutPromise)
return promise.then(() => {
return success(...rest)
}, () => {
return fail(...rest)
})
}
}
const fail = () => {
console.log('由于防抖中断了第一次的请求')
return Promise.resolve() // 忽视它暂时是正确的
}
const success = (rule, value, callback) => {
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('只允许小写字母、数字、短横线(-),且不能以短横线开头或结尾')
}
// 调用接口查询是否重复
return bucketNameCheck({
bucketName: bucketInfo.bucketName
}).then((res) => {
if (res.available) {
nameChecked.value = true
return Promise.resolve()
} else {
// message.warning('该Bucket已存在,或被其他用户占用')
return Promise.reject('该Bucket已存在,或被其他用户占用')
}
})
}
const check = debouncePromise(success, fail, 500)
const rule = {
bucketNameRules() {
return { validator: check, trigger: 'change', required: true }
}
}
即时校验,不是要校验输入字符是否符号要求吗?为啥取消了……
最后一次校验,是整体校验;前面的即时校验,校验的是每个字符。你这样干有点奇怪欸
看了下代码,其实debouncePromise会在输入的时候不断触发,然后你的promise定义在debouncePromsie函数内(也就是闭包)这样每次执行这个方法的时候,你的promise都是undefined,自然不会触发promise.abort()。因为你传递给validator的是一个函数,虽然你的debouncePromise是用了闭包定义了promise,但是函数在执行的时候,它都是一个新的定义。
可以把let promise 的定义提升到外面
let promise;
const debouncePromise = (success, fail, time) => {
return function(...rest) {
if (promise && typeof promise.abort === 'function') {
promise.abort()
}
const timeoutPromise = new Promise((resolve) => {
setTimeout(() => {
resolve(undefined)
}, time)
})
promise = abortPromise(timeoutPromise)
return promise.then(() => {
return success(...rest);
}, () => {
return fail(...rest);
})
}
}
如果想全局使用这套防抖方案,可以参考这篇博客:https://blog.csdn.net/u010899138/article/details/107337700
return { validator: check, trigger: 'change', required: true } 这里的 trigger :'blur' 就不会有这个问题
试试forceUpdate强制更新?
<template>
<input type="text" @change="changeHandle" v-model="value" />
</template>
<script setup>
import { ref } from 'vue'
const value = ref('')
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)
}, time)
})
promise = abortPromise(timeoutPromise)
return promise.then(() => {
return success(...rest);
}, () => {
return fail(...rest);
})
}
}
const success = (...rest) => {
console.log('请求后台接口', rest)
return Promise.resolve('success')
}
const valid = (rule, value) => {
const reg = /^(?![-])[a-z0-9-]{3,63}(?<![-])$/
if (value.length < 3 || value.length > 63) {
return Promise.reject('请输入 3~63 个字符')
} else if (!reg.test(value)) {
return Promise.reject('允许小写字母、数字、短横线(-),且不能以短横线开头或结尾')
}
//调用接口查询是否重复
return bucketNameCheck({
bucketName: value
}).then((res) => {
if (res.available) {
return Promise.resolve()
} else {
return Promise.reject('该Bucket已存在,或被其他用户占用')
}
})
}
const bucketNameCheck = () => {
return new Promise((resolve, reject) => {
setTimeout(() => resolve({
available: Math.random() < 0.5,
}), 1000)
})
}
const fail = (...rest) => {
console.log('由于防抖中断了第一次的请求', rest)
return Promise.resolve({isPause: true}) // 忽视它暂时是正确的
}
const handle = debouncePromise(valid, fail, 2000)
const changeHandle = () => {
console.log('123')
handle('123', value.value).then(({isPause} = {}) => {
if (isPause) {
console.log("中断了请求,重新执行")
} else {
console.log('用户输入的没问题,此时标题框蓝色')
}
}).catch(() => {
console.log('用户输入的有问题标题框红色')
})
}
</script>
<style scoped>
li {
color: #42b983;
}
label {
margin: 0 0.5em;
font-weight: bold;
}
code {
background-color: #eee;
padding: 2px 4px;
border-radius: 4px;
color: #304455;
}
</style>
防抖失效了吗