Готовим идеальный CSS
Не так давно я понял, что работа с CSS во всех моих приложениях — это боль для разработчика и пользователя.
Под катом лежат мои проблемы, куча странного кода и подводные камни на пути к правильной работе со стилями.


Прототипно-ориентированный язык программирования






import React, {Component} from 'react';
import {connect as vBooConnect} from 'react-validation-boo';
import {connect as reduxConnect} from 'react-redux';
import {InputBlock, InputCheckboxBlock, InputRadioGroupBlock, TextareaBlock, SelectBlock} from '../form/default';
class MyForm extends Component {
constructor() {
super();
this.genderOptions = [
{value: '', label: 'Ваш пол?'},
{value: 1, label: 'Мужской'},
{value: 2, label: 'Женский'}
];
this.familyRadioList = [
{value: 1, label: 'холост'},
{value: 2, label: 'сожительство'},
{value: 3, label: 'брак'}
];
}
componentWillMount() {
this.props.vBoo.subscribe('change:input', this.props.onChangeVBooInput);
this.props.vBoo.subscribe('valid:form', this.props.onChangeVBooValid);
}
render() {
let s = this.props.myStore.inputs;
return <Form connect={this.props.vBoo.connect}>
<InputBlock name="name" value={s.name} />
<InputBlock name="email" value={s.email} />
<SelectBlock name="gender" options={this.genderOptions} value={s.gender} />
<InputRadioGroupBlock name="familyStatus" items={this.familyRadioList} value={s.familyStatus} />
<TextareaBlock name="comment" value={s.comment} />
<InputCheckboxBlock name="addition" value="yes" checked={s.addition==='yes'} />
<button onClick={this.sendForm}>
{this.props.vBoo.isValid() ? 'Можно отправлять': 'Будьте внимательны!!!'}
</button>
</Form>
}
}
export default reduxConnect(
store => ({
myStore: { // для наглядности
isValid: false,
inputs: {
email: 'test@mail.ru',
gender: 0,
familyStatus: 1
}
}
}),
dispatch => ({
onChangeVBooInput: (input) => {...},
onChangeVBooValid: (isValid) => {...}
})
)(vBooConnect({
rules: () => ([...]),
labels: () => ({...}),
})(MyForm));



import React, {Component} from 'react';
import {connect, Form, Input, logger} from 'react-validation-boo';
class MyForm extends Component {
sendForm = (event) => {
event.preventDefault();
if(this.props.vBoo.isValid()) {
console.log('Получаем введённые значения и отправляем их на сервер', this.props.vBoo.getValues());
} else {
console.log('Выведем в консоль ошибки', this.props.vBoo.getErrors());
}
};
getError = (name) => {
return this.props.vBoo.hasError(name) ? <div className="error">{this.props.vBoo.getError(name)}</div> : '';
};
render() {
return <Form connect={this.props.vBoo.connect}>
<div>
<Input type="text" name="name" />
{this.getError('name')}
</div>
<button onClick={this.sendForm}>
{this.props.vBoo.isValid() ? 'Можно отправлять': 'Будьте внимательны!!!'}
</button>
</Form>
}
}
export default connect({
rules: () => (
[
['name', 'required'],
]
),
middleware: logger
})(MyForm);


Встретившись в многочисленных местах разработки на Javascript с ситуациями, где необходимо было проводить валидацию значений, стало понятно, что необходимо как-то решить этот вопрос. С этой целью была поставлена следующая задача:
Разработать библиотеку, которая будет давать возможность:
В основе которой будет:
Для достижения этих целей была разработана библиотека валидации quartet.
Angular предоставляет удобный декларативный способ подписки на события в шаблоне, с помощью синтаксиса (eventName)="onEventName($event)". Вместе с политикой проверки изменений ChangeDetectionStrategy.OnPush подобный подход автоматически запускает цикл проверки изменений только по интересующему нас пользовательскому вводу. Иными словами, если мы слушаем (input) событие на <input> элементе, то проверка изменений не будет запускаться, если пользователь просто кликает по полю ввода. Это значительно улучшает
производительность, по сравнению с политикой по умолчанию (ChangeDetectionStrategy.Default). В директивах мы также можем подписаться на события на хост-элементе через декоратор @HostListener('eventName').
В моей практике нередко встречаются случаи, когда обработка конкретного события требуется только при выполнении какого-либо условия. т.е. обработчик выглядит примерно так:

