предисловие
В настоящее время изучаетReact-Native
, застрял наReact-Redux
Потребовалось некоторое время и усилия, чтобы немного разобраться в его принципах и потоке данных, и я нарисовал картинку и объяснил ее. Надеюсь, те, кто читает эту статью, самые лучшиеRedux
Некоторые понимают, если вы не понимаете, вы можете прочитать статью Руан Ифэн. Некоторые объяснения являются личным пониманием и не очень строгие.Если есть ошибки, пожалуйста, поправьте меня.
схема потока данных
Ниже приведен код из блога Ruan Yifeng с некоторыми изменениями, чтобы соответствоватьReact-Native
.
root.js
// 创建一个store全局管理state和操作
const store = createStore(reducer);
// Provider在根组件<App>外面包了一层,App的所有子组件就默认都可以拿到store,通过组件的props传递
export default class Root extends Component {
render() {
return (
<Provider store={store}>
<App/>
</Provider>
)
}
}
app.js
// view提供UI组件
class Counter extends Component {
render() {
// View的状态来自于props,props传递的是store中的state
const { value, onIncreaseClick } = this.props
return (
<div>
<span>{value}</span>
<button onClick={onIncreaseClick}>Increase</button>
</div>
)
}
}
// 将UI组件和容器组件连接起来
const App = connect(
state =>({
value: state.count //输入,将store中的state通过props输入
}),
dispatch =>({ // 输出,将action作为props绑定到View上,用户操作类型在此分发出去
onIncreaseClick: () => dispatch(increaseAction.increase())
})
)(Counter)
export default App
increaseAction.js
// 定义action的类型
export const INCREMENT = 'INCREMENT';
// action 创建函数只是简单的返回一个 action
export function increase(params) {
return {
type: INCREMENT,
data:data
};
}
counterReducer.js
// 提供一个初始的状态
initState={
count: 0
}
// 通过判断Action的类型,返回新的数据改变后的state对象,即使没有任何状态的改变,也要返回一个对象
export default function counter(state = initState, action) {
const count = state.count
switch (action.type) {
case INCREMENT:
return { count: count + 1 }
default:
return state
}
}
Поток данных можно увидеть на рисунке ниже, сначала сView
В качестве примера, о котором я расскажу позже, эта картина понимает,React-Redux
Это почти понятно.
1. В этом примереView
Компоненты предоставляют только пользовательский интерфейс, а не свой собственныйstate
и операций, так что же послужило причиной изменения интерфейса?
даView
себяprops
, мы знаем, что начальное состояние компонента даетсяprops
решение, хотя и без моего собственногоstate
, если егоprops
Изменения происходят, и интерфейс тоже меняется.
2,View
изprops
Что обеспечивает содержание, несколькоView
серединаprops
Как отличить?
глобально уникальный в приложенииstore
серединаstate
При условии, что все состояние хранится в объекте, отличающемся ключом.<Provider store={store}> <App/> </Provider>
Эта строка кода реализует привязку, уникальную для приложения.store
.
3.store
Как это произошло?
пройти черезstore = createStore(reducer)
Создайте,reducer
Возвращается именно измененный объект состояния.
Первые три вопроса объясняют поток данных в левой половине рисунка выше.reducer——(store/state)——provider——(state/props)——view
4.action
как сreducer
связанный, илиreducer(state,action)
Откуда происходит действие в этой функции?
даstore.dispatch(action)
Внутренняя обработка, посмотрите сначалаcreateStore(reducer)
Эта функция, сокращенный код выглядит следующим образом:
function createStore = ( reducer ) => {
let currentState; // 内部的状态
let listeners = []; //所有的监听者
const getState = () => currentState; // 获取store中的state
// dispatch的操作就是内部执行reducer()函数,action和reducer在这儿产生交集,并且通知所有的监听者
const dispatch = ( action ) => {
currentState = reducer(state, action); // 更新state
listeners.forEach(listener => listener());
}
// 订阅事件
const subscribe = ( listener ) => {
listeners.push(listener);
return ()=>{
listeners = listeners.filter(l => l !== listener)
}
}
return {
getState,
dispatch,
subscribe
}
}
Почему он не показывает, что вызов записиstore中
изdispatch
, это всеReact-Redux
серединаconnect
а такжеProvider
кредит, если вы не используете их, вышеapp.js
Код должен быть следующим:
class Counter extends Component{
componentWillMount(){
// 订阅状态变化
store.subscribe((state)=>this.setState(state))
}
render() {
return (
<div>
<span>{value}</span>
// 点击后dispatch事件类型
<button onClick={()=>store.dispatch(increaseAction.increase())}>Increase</button>
</div>
)
}
}
5.reducer()
После выполнения функции, как изменитьstate
из?
см. вопрос 4createStore
Код можно упростить следующим образом:
function createStore = ( reducer ) => {
let currentState; // 内部的状态
const getState = () => currentState; // 获取store中的state
// 更新state
const dispatch = ( action ) => {
currentState = reducer(state, action);
}
return {
getState,
dispatch,
}
}
Вышеуказанные две проблемы были решены и объяснили поток данных в правой половине вышеуказанного рисунка.view——(action)——dispatch——(action)——reducer
, два цикла данных объединяются вместе, чтобы сформировать круг, который завершает великую гармонию жизни. Как показано ниже:
Несколько редукторов
Прочитав приведенный выше анализ, давайте расширим, на картинке выше есть только одинreducer
, в обычном приложении много представлений и, естественно, много соответствующихreducer
, то интерфейсaction
как это соответствуетreducer
А как насчет связанного?
Если вышеуказанный проект добавляетloginReducer.js
файл, код такой:
loginReducer.js
// 提供一个初始的状态
initState={
login: false
}
// 通过判断Action的类型,返回新的数据改变后的state对象,即使没有任何状态的改变,也要返回一个对象
export default function login(state = initState, action) {
const login = state.login
switch (action.type) {
case INCREMENT:
return { login: !login }
default:
return state
}
}
этоreducer
Просто выполните операцию, получитеINCREMENT
При этом типе операции состояние входа меняется один раз на обратное. Если я нажму кнопку еще раз, изменится ли статус входа в систему, когда число счетчиков увеличится? ответМогу! Так почему?
МогуПредпосылка: вы используете следующий код:
const rootReducer = combineReducers({
counter: counter,
login:login
});
store=createStore(rootReducer);
combineReducers
Объединитьreducer
, так называемое слияние заключается в том, чтобы поставитьreducer
Функциональные объекты объединены в единыйreducer
Функция, она пройдет все подreducer
членов и интегрировать результаты в единое дерево состояний, поэтому существует только одинreducer
, повторюсь, только один в концеreducer
функция!combineReducers
Грубый код выглядит следующим образом:
export default function combineReducers(reducers) {
var reducerKeys = Object.keys(reducers)
var finalReducers = {}
//提取reducers中value值为function的部分
for (var i = 0; i < reducerKeys.length; i++) {
var key = reducerKeys[i]
if (typeof reducers[key] === 'function') {
finalReducers[key] = reducers[key]
}
}
var finalReducerKeys = Object.keys(finalReducers)
return function combination(state = {}, action={}) {
var hasChanged = false
var nextState = {}
/**
* 遍历访问finalReducers
*/
for (var i = 0; i < finalReducerKeys.length; i++) {
var key = finalReducerKeys[i]
var reducer = finalReducers[key]
/**
*将state按照reducer的名字分离
* 每个key都对应着state
*/
var previousStateForKey = state[key];
var nextStateForKey = reducer(previousStateForKey, action)
nextState[key] = nextStateForKey
hasChanged = hasChanged || nextStateForKey !== previousStateForKey
}
return hasChanged ? nextState : state
}
}
Из приведенного выше кода видно, что когдаdispatch
Одинaction
,всеreducer
Функция будет выполнена один раз, поaction.type
изменить соответствующиеstate
, чтобы все подписки соответствовалиstate
изView
изменится. Итак, ответ на поставленный выше вопрос:Могу.
Наконец, поставьте еще одну картинку, то есть несколькоreducer
а такжеaction
Диаграмма направления потока данных времени.
store
,state
,reducer
,action
На самом деле в итоге он один, мы просто делим его на несколько по логике кода, с четкими слоями, которые легко разрабатывать и читать.
Суммировать
Резюме предложения,View
Отвечает за пользовательский интерфейс,redux
БудуView
серединаstate
и операции сосредоточены вstore
управления, а затем черезprops
будет измененstate
содержимое переданоView
И интерфейс меняется. Пользовательский интерфейс,View
пройти черезdispatch
выполнить соответствующие операции, а затемActionType
а такжеData
сдаватьreducer
функция, согласноActionType
а такжеData
Исправлятьstate
.
Спасибо
- Подробное объяснение метода подключения реакции-редукции
- редукционная китайская маркировка
- Использование React-Redux
наконец
Если вам это нравится, пожалуйста, хотите и следуйте.
Добро пожаловать в мойGitHubДомашняя страница, если хотитеfollow
Я.