Статья впервые опубликована на:GitHub.com/US TB-Вуд, умри, о ты…
написать впереди
Развитие интерфейсных технологий меняется с каждым днем, и появление vue, react, angular и т. д. принесло нам новый опыт разработки. Однако с инновациями в технологиях и повышением сложности интерфейсных страниц появились соответствующие решения для хранения и управления данными, такие как localStorage, eventBus, vuex, redux, mobx, rxjs и т. д., поэтому необходимо изучить государственное управление. Так что я недавно потратил некоторое время на изучение этого. В процессе анализа могут быть отклонения в собственном понимании или различия в вашем понимании.Вы можете оставить комментарий или написать мне в личные сообщения.
Эта статья будет заключаться из следующих разделов:
- представление на основе данных
- Межкомпонентный обмен данными и шина событий
- Поток данных одного элемента (vuex && redux)
- лучше мобкс
- Реализовать супер простую версию redux и react-redux
представление на основе данных
В настоящее время самые популярные интерфейсы React и Vue, используемые дизайнерские идеи, представляют собой представления, управляемые данными, то есть UI = f (состояние).При изменении страницы вам не нужно заботиться об изменениях DOM, только изменения состояния. Процесс сопоставления состояния с пользовательским интерфейсом обрабатывается фреймворком. Для решения проблем с производительностью был создан Virtual DOM. С помощью Virtual DOM представления, управляемые данными, можно просто разбить на четыре этапа:
- Изменения данных, создание нового виртуального DOM
- Сравните сходства и различия между новым виртуальным DOM и старым виртуальным DOM с помощью алгоритма сравнения.
- Создание разницы между старыми и новыми объектами (патч)
- Перебирать объекты diff и обновлять DOM
С react и vue процесс state => UI имеет хорошую практику, но наоборот,Как разумно изменить состояние в пользовательском интерфейсе, стало новой проблемой.. С этой целью Facebook предложил идею потока. Подробнее см. в статье Руан Ифэн.Начало работы с архитектурой Flux. Проще говоря, Flux — это архитектурная идея, она считает, что есть некоторые проблемы с предыдущей инфраструктурой MVC, поэтому намерена использовать новое мышление для управления потоком данных.
Межкомпонентный обмен данными и шина событий
Данные можно просто разделить на две части: данные по компонентам и данные внутри компонентов. Большая часть данных в компоненте связана с пользовательским интерфейсом, например, установлен ли флажок переключателя или нажата кнопка. Их можно назвать внутрикомпонентными данными о состоянии. В реакции есть концепция, называемая кукольным компонентом, и данные, хранящиеся в нем, являются данными состояния в компоненте. На самом деле, многие библиотеки компонентов пользовательского интерфейса на рынке, такие как дизайн элементов и муравьев, предоставляют марионеточные компоненты. Другой тип данных — кросс-компонентные данные.Например, родительский компонент вызывает отключение дочернего компонента.Как только мы сталкиваемся с взаимодействием кросс-компонента, проблемы, с которыми мы сталкиваемся, начинают усложняться. В настоящее время необходим механизм для управления связью между родительскими и дочерними компонентами и одноуровневыми компонентами. Родительский компонент дочернему компоненту является передачей реквизита.То, как дочерний компонент реагирует на родительский компонент, заключается в том, что родительский компонент передает функцию обработки дочернему компоненту, который вызывается дочерним компонентом, так что данные передается из параметра функции в родительский компонент. Метод обработки Vue заключается в том, что дочерний компонент передает данные из параметра функции родительскому компоненту через функцию $emit, а родительский компонент получает вызов.
EventBus — это центральная коммуникация, а provider — это объект или функция, которая возвращает объект. Этот объект содержит свойства, которые можно внедрить в его потомков:
Вариантами ввода могут быть: массив строк или объект. Затем используйте введенное значение в качестве ввода данных:
Но для нескольких представлений, которые должны полагаться на одно и то же состояние или поведение из разных представлений, необходимо изменить одно и то же состояние. Полагаться исключительно на связь между компонентами кажется немного безвкусным.
Поток данных одного элемента (vuex && redux)
Давайте используем картинку, чтобы представить поток данных следующего сокращения и реагировать соответственно:
То, как передаются данные Redux, просто означает, что каждое событие будет отправлять действие, действие запускает редюсер через отправку и напрямую генерирует новое состояние на основе старого состояния, чтобы заменить исходное состояние в хранилище верхнего уровня.
Redux подчеркивает три основных принципа:
- уникальный источник данных
- сохранить состояние только для чтения
- Изменения данных могут быть сделаны только с помощью чистых функций
В todo-list, например, код размещен на github:Github
Уникальный источник данных:Уникальный источник данных означает, что данные о состоянии приложения должны храниться только в одном хранилище. Дерево состояний Store приложения todo-list выглядит следующим образом:
{
todos: [
{
text: 'First todo',
completed: false,
id: 0
},
{
text: 'Second todo',
completed: false,
id: 1
}
],
filter: 'all'
}
Держите состояние читабельным:Чтобы изменить состояние Store, это необходимо сделать, отправив объект действия. Согласно UI=render(state), для управления рендерингом пользовательского интерфейса необходимо изменить состояние приложения, но способ изменения состояния заключается не в изменении значения состояния, а в создании нового объекта состояния. и верните его в Redux, а Redux выполнит новое состояние сборки.
Изменения данных могут быть сделаны только с помощью чистых функций:Редюсер должен быть чистой функцией, и формат каждой функции редуктора следующий: редуктор(состояние, действие):
import {ADD_TODO, TOGGLE_TODO, REMOVE_TODO}from './actionTypes.js';
export default (state = [], action) => {
switch(action.type) {
case ADD_TODO: {
return [
{
id: action.id,
text: action.text,
completed: false
},
...state
]
}
case TOGGLE_TODO: {
return state.map((todoItem) => {
if (todoItem.id === action.id) {
return {...todoItem, completed: !todoItem.completed};
} else {
return todoItem;
}
})
}
case REMOVE_TODO: {
return state.filter((todoItem) => {
return todoItem.id !== action.id;
})
}
default: {
return state;
}
}
}
Давайте используем картинку с официального сайта, чтобы представить следующий vuex:
Можно сказать, что Vuex — это инструмент управления состоянием, специально разработанный для Vue. В отличие от Redux, который использует неизменяемые данные для представления состояния, в Vuex нет редуктора для создания нового состояния взамен старого, а состояние в Vuex можно изменить. Причина этого связана с механизмом работы Vue.Vue реализует двустороннюю привязку представления и данных на основе геттера/сеттера в ES5.Поэтому изменение состояния в Vuex может быть уведомлено соответствующей инструкцией в представлении. через сеттер для реализации обновления представления.
Состояние в Vuex поддается изменению, и способ изменения состояния — не действия, а мутации. Единственный способ изменить состояние в хранилище Vuex — отправить мутацию.
Поток данных vuex выглядит просто:
- Запустите действие в представлении и передайте необходимые параметры в соответствии с реальной ситуацией.
- Запустите нужную мутацию в действии и измените состояние в функции мутации
- Двусторонняя привязка через геттер/сеттер автоматически обновит соответствующее представление.
лучше мобкс
MobX делает управление состоянием простым и расширяемым за счет прозрачного применения функционального реактивного программирования (TFRP). Ниже приведена блок-схема mobx:
Сравнивая mobx и redux, есть небольшая разница: если redux воплощает в себе функциональное программирование, то mobx воплощает в себе больше объектно-ориентированных функций. mobx состоит из нескольких пунктов:
- Наблюдаемый. Его состояние является наблюдаемым, будь то примитивный тип данных или ссылочный тип данных, его можно преобразовать в наблюдаемое значение, используя (@)observable в MobX. источник
- Реакции. Он содержит различные концепции, основанные на обновлении наблюдаемых данных, приводящем к вычисляемому значению (вычисляемым значениям), или отправке сетевых запросов и обновлении представлений и т. д., все они относятся к категории ответа, которая также является реактивным программированием (Reactive Programming ) в JavaScript приложение .
- Действия. Он эквивалентен источнику всех ответов, таких как действия пользователя в представлении или изменения наблюдаемых данных, вызванные ответом на сетевой запрос.
Реализовать упрощенную версию redux и react-redux
Простая реализация методов redux createStore, диспетчеризации, подписки, редуктора, getState.
function createStore (reducer) {
let state = null
const listeners = []
const subscribe = (listener) => listeners.push(listener) // 观察者模式实现监控数据变化
const getState = () => state
const dispatch = (action) => { //用于修改数据
state = reducer(state, action) // reducer接受state和action
listeners.forEach((listener) => listener())
}
dispatch({}) // 初始化 state
return { getState, dispatch, subscribe } // 暴露出三个方法
}
Простая реализация методов react-redux Provider, connect, mapStateToProps, mapDispatchToProps.
Реализуйте метод Provider:
export class Provider extends Component {
static propTypes = {
store: PropTypes.object,
children: PropTypes.any
}
static childContextTypes = {
store: PropTypes.object
}
getChildContext () {
return {
store: this.props.store
}
}
render () {
return (
<div>{this.props.children}</div>
)
}
}
Это будет работать
<Provider store={store}>
</Provider>
Оберните корневой компонент.
Реализуйте метод подключения и согласитесь на передачу mapStateToProps и mapDispatchToprops:
export const connect = (mapStateToProps, mapDispatchToProps) => (WrappedComponent) => {
class Connect extends Component {
static contextTypes = {
store: PropTypes.object
}
constructor () {
super()
this.state = {
allProps: {}
}
}
componentWillMount () {
const { store } = this.context
this._updateProps()
store.subscribe(() => this._updateProps())
}
_updateProps () {
const { store } = this.context
let stateProps = mapStateToProps
? mapStateToProps(store.getState(), this.props)
: {} // 防止 mapStateToProps 没有传入
let dispatchProps = mapDispatchToProps
? mapDispatchToProps(store.dispatch, this.props)
: {} // 防止 mapDispatchToProps 没有传入
this.setState({
allProps: {
...stateProps,
...dispatchProps,
...this.props
}
})
}
render () {
return <WrappedComponent {...this.state.allProps} />
}
}
return Connect
}
Суммировать
Если стек технологий проекта основан на vue, vuex для управления состоянием, несомненно, является лучшим выбором. Но если стек технологий основан на React, выбор между redux и mobx — вопрос личного мнения, и мудрые видят мудрость. Причиной выбора mobx может быть то, что процессов не так много, как redux, и для изменения состояния приходится обращаться к нескольким файлам, чтобы найти код. Кроме того, стоимость обучения невелика, и вы можете начать работу, прочитав документацию. Но недостаток в том, что он слишком бесплатный, и в нем очень мало условностей, из-за чего делать масштабные проекты немного безвкусно. Но редукс накладывает на разработчиков множество ограничений, но эти ограничения не так-то просто написать беспорядочно при выполнении больших проектов.
Справочная статья
редукционная китайская документация
Говоря об управлении состоянием внешнего интерфейса (часть 1)
Дважды подумайте о внешнем управлении состоянием
Управление внешними данными и выбор интерфейсной платформы
Можете обратить внимание на мой паблик-аккаунт «Muchen Classmate», фермера на гусиной фабрике, который обычно записывает какие-то банальные мелочи, технологии, жизнь, инсайты и срастается.