Как я уже писал в своих предыдущих статьях я работал и с polymer и с vue в связке с redux. Поэтому хотелось бы поделиться опытом, связанным со спецификой использования redux в данных библиотеках. Рассматривать будем на простейших атомарных контролах: нативных (input, checkbox) и обернутых, в виде компонентов данных библиотек.
В статье я опуская описание настройки интеграции redux
с polymer и vue, а так же описание азов самого redux, дабы не эту тему хочу раскрыть в статье.
0. Введение
Сначала вспомним один из основных принципов redux:
The only way to change the state is to emit an action, an object describing what happened.
Исходя из него ясно, что напрямую мы не можем изменить состояние, а сделать это можем только через диспатч экшена после наступление необходимого event'а.
Схематично это можно изобразить так:
Как видим наблюдается односторонний поток данных.
1. Нативные контролы
polymer
Очень удобная вещь в polymer
при связке с redux
дак это односторонний биндинг.
template:
<input value="[[propFromReduxStore]]" on-change="changeText"></input>
js-code:
changeInput: function(e) {
this.dispatch("setText", e.currentTarget.value);
}
Поэтому с input все, в принципе стандартно: при событии change
диспатчим action и после чего измененное значение попадает в propFromReduxStore
и контрол перерендерится уже с новым значением.
vue
C vue
немного другая ситуация, в нем нет как такагого одностороннего биндинга, как в polymer
. Но подобную функциональность можно достигнуть через модификатор sync
template:
<input :value.sync="propFromReduxStore" @change="changeText"></input>
js-code:
changeInput: function(e) {
this.actionsRedux("setText", e.currentTarget.value);
}
Остальное все как и в варианте с polymer
.
2. Компоненты
С компонентами сложней, так как это совокупность методов, событий, «завернутые» в компоновку html
-элементов в виде шаблона.
Схематичное описание работы компонента:
Как видим о событии компонента мы узнаем уже обо всем постфактум, что противоречит принципу redux
описанному выше. И что бы избежать неконсистентной ситуации, когда контрол уже перерендерился в виду своего внутреннего состояния, а прибинденная модель еще не поменялась через action
и не соответствует данному представлению необходимо производить дополнительные действия для блокировки прямого изменения state.
polymer
На примере компонента paper-checkbox
template:
<paper-checkbox checked="[[propFromReduxStore]]" on-tap="changeCheck"></paper-checkbox>
js-code:
changeCheck: function(e) { //Здесь ловим клик по компоненту
//Предотвращаем bubbling события, что бы компонент сразу не перерендерил компонент
e.stopPropagation();
this.dispatch("setChecked", !this.propFromReduxStore);
}
vue
На примере компонента el-checkbox
template:
<el-checkbox v-model="propFromReduxStore" @click.stop.native="changeCheck" >
</el-checkbox>
js-code:
changeCheck: function() {
this.actionsRedux("setChecked", !this.propFromReduxStore);
}
В компоненте может даже и не быть события click
, а если и есть, то узнаем мы об его наступлении уже постфактум, не говоря уже об его подалении, но зато есть модификатор native, который позволяет получить доступ ко всем возможным нативным событиям. Так же есть модификатор stop
, который даже позволит нам не писать e.stopPropagation(), как это было с polymer
. Малость, а приятно.
React
не рассмотрел, так как на практике его не использовал, если не считать jsx
-темплейтов в vue
, но это совершенно не то. Но все-таки, насколько я наслышен от коллег по цеху, там таких проблем нет, в виду внутренней архитектуры обработки событий.
Автор: Анатолий