开发者问题收集

Vue.js vuelidate:如何消除异步自定义验证器的抖动?

2018-03-08
6553

我有一个验证器,用于检查用户名是否已在数据库中注册。它工作正常,除了请求随每个输入的字符一起发送到服务器这一事实 - 这太频繁了。因此,我尝试对用户名变量值的设置进行去抖动,但我得到的只是:

Uncaught TypeError: Cannot read property 'value' of undefined 
at a.NHnr.q.methods.debounceUsername.H.a.debounce.leading

Vue 脚本:

import uniqueUsername from '../validation/uniqueUsername'
import _ from 'lodash'

export default {
    name: "signUpPage",
    data() {
      return {
        credentials: {
          username: ''
        }
      }
    },
    methods: {
      debounceUsername:
        _.debounce(function (e) {
          this.credentials.username = e.target.value;
        }, 200, {leading: false, trailing: true})
    },
    validations: {
      credentials: {
        username: {
          uniqueUsername: uniqueUsername
        }
      }
   }
}

Html:

    <b-field :label="msg('usernameLabel')"
             :class="{ 'form-group--error': $v.credentials.username.$error }">
      <b-input size="is-large" type="text" class="form__input"
               icon="account" name="username" v-on:input="debounceUsername" autofocus="">
      </b-input>
    </b-field> 
//b-field and b-input are from buefy library

自定义验证器 (uniqueUsername.js):

import axios from 'axios'

export default value => {
  if (value.trim().length === 0) return true;
  let usernameUnique;
  return new Promise(async function (resolve) {
    await axios('/isUsernameUnique', {
      method: "post",
      data: value,
      headers: {'Content-type': 'text/plain'}
    }).then((response) => usernameUnique = response.data);
    if (usernameUnique) resolve('username is unique');
  });
};
2个回答

One solution is to check when the user focused out of input field (blur) and then to run the async validations.So:

<input @blur="$v.username.$touch" v-model.lazy="username" />

The script:

export default {
  data () {
   return {
    username: ''
   }
  },
  validations: {
    username: {
     required,
     isUnique(username) {
       if (username === '') return true
       return axios.get('/checkUsername')
                 .then(res => {
                   return res.data //res.data has to return true or false after checking if the username exists in DB
                 }) 
     }
    }
  }
}

Note: in order to work this code you have to import axios and required from vuelidate

Also keep in mind.The backend has to return false if the username is unique in order the above code to work correctly

Roland
2018-03-08

我找到了答案。 我必须将

this.credentials.username = e.target.value;

更改为:

this.credentials.username = e;

现在它可以正常工作 - 发送请求的频率现在最多为每 200 毫秒一次

Jakubeeee
2018-03-09