Внутри Редукса (1)
Кровавый случай, вызванный проблемой
В процессе собеседования у блогера интервьюер спросил: «Посмотрите на свое резюме, использовались и Vue, и React, можете ли вы сказать мнеВ чем разница между Vue и React?", а потом сказал это, так! Бывал кровавый случай, когда я отвечал на Vuex и Redux, интервьюер спросил, почему Redux всегда возвращает новыйstate
? вернуть старыйstate
почему бы нет ? Излишне говорить, что результаты интервью, ГГ.
вдохновленный
Спустя больше полумесяца, когда я подытожил свой опыт собеседования, я прочитал исходники Redux, ojbk, я запутался, а потом зашел на гитхаб почитать толкования каких-то старших братьев, а потом сам обобщил, написал колонку, используя для дальнейшего изучения
Базовое понимание
Что такое Редукс?
Redux — это контейнер состояния JavaScript, предоставляющий решение для предсказуемого управления состоянием, как описано на официальном сайте:
// Redux is a predictable state container for JavaScript apps.
Так что же он может сделать?
// It helps you write applications that behave consistently, run in different environments (client, server, and native) and are easy to test.
// On top of that, it provides a great developer experience, such as live code editing combined with a time traveling debugger.
Три принципа
-
Единый источник достоверной информации: для всего приложения
state
хранятся в дереве состояний и существуют только в одном и только одном хранилище -
состояние доступно только для чтения: единственный способ изменить состояние — запустить
action
, а затем передать действиеtype
А потом отправка отправки. Невозможно напрямую изменить состояние приложения -
Изменение состояния выполняется чистыми функциями: чтобы описать, как действие изменяет дерево состояний, необходимо написать
reducers
Обрезка
Здесь давайте сначала узнаем о хранилище, промежуточном программном обеспечении, действии, редюсере и т. д.
store
здесьstore
Он генерируется методом createStore(reducers, preloadedState,Enhancer), предоставляемым Redux. Из сигнатуры функции для создания хранилища необходимо передать редукторы, а также можно передать второй необязательный параметр состояния инициализации (preloadedState). Третий параметр вообще промежуточное ПОapplyMiddleware(thunkMiddleware)
, посмотрите на код, он более интуитивен
import { createStore, applyMiddleware } from 'redux'
import thunkMiddleware from 'redux-thunk' // 这里用到了redux-thunk
const store = createStore(
reducers,
state,
applyMiddleware(thunkMiddleware) // applyMiddleware首先接收thunkMiddleware作为参数,两者组合成为一个新的函数(enhance)
)
Основной API в редуксе -createStore
, хранилище, созданное методом createStore, представляет собой объект, который сам содержит 4 метода:
-
getState(): Получить текущее состояние в магазине.
-
dispatch(action) : отправить действие и вернуть это действие, это единственное, что может изменить данные в хранилище. Способ.
-
subscribe(listener) : зарегистрируйте прослушиватель, который вызывается при изменении хранилища.
-
replaceReducer(nextReducer) : обновите редуктор в текущем хранилище, обычно вызывайте этот метод только в режиме разработки.
middleware
На рисунке ниже показан простой сценарий синхронного потока данных в Redux.После нажатия кнопки в обратном вызове отправляется действие.После получения действия редюсер обновляет состояние и уведомляет представление о повторной отрисовке.
Односторонний поток данных, кажется, что нет никаких проблем. Однако, если вам нужно распечатать информацию о каждом действии для отладки, вы должны изменить реализацию диспетчера или редуктора, чтобы иметь функцию печати журналов.
Для другого примера, после нажатия кнопки вам нужно перейти к серверу, чтобы сначала запросить данные, и только после того, как данные будут возвращены, можно повторно отобразить представление, В это время мы надеемся, что диспетчеризация или редьюсер имеет функцию асинхронный запрос. Другой пример: после возврата данных асинхронного запроса печатается журнал, затем запрашиваются данные, печатается журнал, а затем отображается.
Перед лицом различных бизнес-сценариев, очевидно, не универсально просто модифицировать код диспетчеризации или редуктора.Redux опирается на идею промежуточного программного обеспечения в Node.js Koa.Редуктор в Redux больше связан с логикой преобразования данных , такПромежуточное ПО улучшает диспетчеризацию.
Action
// 引用官网的介绍
// Actions are payloads of information that send data from your application to your store.
// They are the only source of information for the store
// You send them to the store using store.dispatch().
Действия — это полезные данные, которые передают данные из приложения в магазин. Это единственный источник данных магазина. Проще говоря, Action — это тип сообщения, которое сообщает Redux, что делать, когда пришло время это сделать, и передает его в Redux с соответствующими данными.
Действие — это простой объект, который должен иметь атрибут типа, который используется для обозначения типа действия (редьюсер определяет выполняемую логику), а другие атрибуты могут быть настроены пользователем. Такие как:
const START_FETCH_API = 'START_FETCH_API'
{
type: START_FETCH_API,
data: {
id: itemId,
value: 'I am Value'
}
}
Action Creator
Взгляните на введение на официальном веб-сайте: Action Creator — это именно то, что нужно — функции, которые создают действия Легко спутать термины «действие» и «создатель действия», поэтому постарайтесь использовать правильный термин. То есть: Action Creator в Redux просто возвращает действие.
function fetchStartRequestApi(jsondata) {
return {
type: START_FETCH_API,
data: jsondata
}
}
Мы знаем, что Redux развился из Flux.В традиционном Flux создатели действий часто запускают отправку после вызова. Например:
function fetchStartRequestApiDispatch(jsondata) {
const action = {
type: START_FETCH_API,
data: jsondata
}
dispatch(action)
}
Однако в Redux нам нужно только передать результат, возвращенный создателями действий, в dispatch(), чтобы завершить процесс инициации отправки или даже создать被绑定的 Action Creators
автоматически отправлять
// example 1
dispatch(fetchStartRequestApi(jsondata))
// example 2
const boundFetchStartRequestApiDispatch = jsondata => dispatch(fetchStartRequestApi(jsondata))
Кто-то здесь вот-вот упадет в обморок, что такое dispatch()? На самом деле, как упоминалось ранее, создается с помощью createStore().store
Object, у него есть метод: dispatch(action), метод dispatch() можно вызвать прямо в магазине через store.dispatch(), но в большинстве случаев мы будем использовать хелпер connect(), предоставленный react-redux для вызов. bindActionCreators() может автоматически привязывать несколько создателей действий к методу dispatch().
Reducers
// 引用官网的介绍
// Reducers specify how the application's state changes in response to actions sent to the store.
// Remember that actions only describe what happened, but don't describe how the application's state changes
Как упоминалось выше, Reducers должны быть чистой функцией, которая обрабатывает обновления состояния в соответствии с действиями.Если обновления нет или встречается неизвестное действие, она возвращает старое состояние, в противном случае — новый объект состояния. __Примечание. Вы не можете изменить старое состояние, вы должны сначала скопировать состояние, а затем изменить его, или вы можете использовать функцию Object.assign для создания нового состояния. __Конкретная причина, которую мы узнаем, когда читаем исходный код~
Никогда не выполняйте эти операции в редукторах:
-
Изменить входящие параметры;
-
Выполнение операций с побочными эффектами, таких как запросы API и переходы по маршруту;
-
вызывать нечистые функции, такие как Date.now() или Math.random();
Последний пример кода ниже помогает переварить, отправить запрос и получить список музыки.
// action.js
/*
* action 类型
*/
export const START_FETCH_API = 'START_FETCH_API'
export const STOP_FETCH_API = 'STOP_FETCH_API'
export const RECEIVE_DATA_LIST = 'RECEIVE_DATA_LIST'
export const SET_OTHER_FILTERS = 'SET_OTHER_FILTERS'
/*
* 其它的常量
*/
export const otherFilters = {
SHOW_ALL: 'SHOW_ALL',
SHOW_ACTIVE: 'SHOW_ACTIVE'
}
/*
* action 创建函数
*/
export function startFetchApi() {
return {
type: START_FETCH_API
}
}
export function stopFetchApi() {
return {
type: STOP_FETCH_API
}
}
export function receiveApi(jsondata) {
return {
type: RECEIVE_DATA_LIST,
data: jsondata
}
}
export function setOtherFilters (filter) {
return {
type: SET_OTHER_FILTERS,
data: filter
}
}
// 异步
export const fetchMusicListApi = (music_id) => dispatch => {
dispatch(startFetchApi())
fetch({
url: url,
method: 'POST',
data: {
music_id: music_id
}
}).then((res) => {
dispatch(stopFetchApi())
dispatch(receiveApi())
}).catch((err) => {
console.log(err)
})
}
// reducers.js
// 引入 action.js
import { otherFilters } from './action'
// 初始 state
const initialState = {
otherFilters: otherFilters.SHOW_ALL,
list: [],
isFetching: false
}
function reducers(state, action) {
switch(action.type) {
case SET_OTHER_FILTERS:
return Object.assign({}, state, {
otherFilters: action.payload.data
})
case START_FETCH_API:
return Object.assign({}, state, {
isFetching: true
})
case STOP_FETCH_API:
return Object.assign({}, state, {
isFetching: false
})
case RECEIVE_DATA_LIST:
return Object.assign({}, state, {
list: [ ...action.payload.data ]
})
default:
return state
}
}
Уведомление
-
Не изменять состояние. использовать
Object.assign()
Создается новая копия. Object.assign(state, {otherFilters: action.payload.data}) нельзя использовать таким образом, потому что это изменит значение первого параметра. Вы должны установить первый параметр на пустой объект -
Возвращает старое состояние в случае по умолчанию. Столкнувшись с неизвестным действием, обязательно вернитесь к старому состоянию.
Сомнение в уме
-
Как bindActionCreators() автоматически помогает мне привязать действия к отправке?
-
Что такое чистая функция?
-
Почему редюсер должен быть чистой функцией?
-
Почему можно изменить состояние только через действие, в чем проблема с прямым изменением?
-
Как bindActionCreators() автоматически помогает мне привязать действия к отправке?
-
Почему редюсеры должны возвращать старое состояние в случае дефолта?
-
...
Продолжение следует
Я еще не дочитал, а там еще следующее, просто хочу еще немного разобраться, а потом продолжить писать конспект, цель прочитать самому, в том числе и новичкам, надеюсь покажете милосердие, вы можете пропустить, если вам не интересно~, перейдите прямо на github, чтобы увидеть исходный код, портал находится здесь:Redux
Обновление 2019.01.03, здесь следующее:«Почему редукс возвращается к кровавому делу, вызванному новым состоянием (2)»
Ссылки по теме
-
Китайская документация Redux:Талант Горячее цинкование Just.org/docs/basics…
-
Английская документация Redux:Горячее цинкование.Просто название .org/basics/AC…
-
github : GitHub.com/PDK София/Нет…