Я пытался написать довольно простую логику проверки на VueJS и наткнулся на, казалось бы, простую проблему, для которой мне трудно найти подходящее решение.
В моем компоненте Vue у меня есть объект данных, который является простым экземпляром класса Form.
export default {
data: function () {
return {
form: new Form([
{ email: '' },
{ password: '' },
]),
}
},
methods: {
handleSubmit () {
// A callback in which an API request is performed using something like Axios.
this.form.submit((data) => performApiRequest(data));
},
}
Этот класс Form имеет свойство ошибок, которое содержит ошибки для полей ввода в форме. Чтобы определить, присутствует ли ошибка для данного поля, добавляется метод hasError.
export default class Form {
constructor (fields = {}) {
this.fields = fields;
this.errors = {};
}
hasError (error) { return this.errors.hasOwnProperty(error); }
submit (action) {
action(this.fields)
.catch((error) => {
this.errors = error.response.data.errors;
});
}
}
В шаблоне компонента проверяем ошибки таким образом:
<input type = "email" v-model = "form.email">
<span class = "error" v-if = "form.hasError('email')">{{ form.errors.email }}</span>
Все это прекрасно работает, но всякий раз, когда одно из входных значений в моей форме изменяется, метод hasError срабатывает для всех полей.
Итак, если мы добавим 20 полей ввода с 20 диапазонами ошибок, этот метод будет вызываться 20 раз при вводе одного символа в любом из полей ввода.
Это имеет смысл, поскольку hasError не является вычисляемым свойством и, следовательно, не имеет преимущества кэширования, которое есть у вычисляемого свойства.
Мне трудно понять, как реорганизовать это, чтобы воспользоваться некоторой формой кэширования, принимая во внимание, что я хочу, чтобы класс Form можно было повторно использовать в нескольких компонентах.
Как можно было бы реализовать эту функциональность повторно используемым способом?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете сделать каждое поле формы объектом со значением и ключом ошибки.
{ value: "thevalue", error: "some error" }
Затем в своем шаблоне используйте
<input type = "email" v-model = "form.email.value">
<span class = "error" v-if = "form.email.error">{{ form.email.error }}</span>
Это также позволит вам иметь проверки для каждого поля или другое поведение.
{
value: "thevalue",
error: "some error",
validations: [<array of validation functions>], // like minLength/maxLength,
// built-in validations for some common types
// like email or isDigits or alphanumeric etc
type: "email"
}
Что, если теперь я хочу иметь свойство для проверки наличия ошибок? Метод hasErrors в экземпляре Form не будет кэшировать результат. Наличие hasErrors в качестве вычисляемого свойства в моем компоненте кажется проблемой ответственности и не может использоваться повторно. Я мог бы поместить это вычисляемое свойство в миксин, но тогда у меня есть два отдельных требования для чего-то, что, скорее всего, должно быть просто одним (класс Form в данном случае).
Я полагаю, у вас может быть поле hasErrors, и каждый раз, когда значение поля и/или ошибка поля обновляются, обновляйте hasErrors, например hasErrors = thisField.error ? true : hasErrors.
Я не думаю, что вы получите большое преимущество в производительности от механизма кэширования (вычисляемого или иного) - директивы
v-if, скорее всего, будут запускать свое выражение при каждом цикле изменения, а то, что у вас есть в методеhasError(), довольно скудно. Проблема с кешем заключается в том, чтобы заставить его распознавать, когда происходят изменения, поэтому больше кода и сложности.