React
reduc 是(React全家桶)的核心成员
一、什么是Redux?
- 我们一直通过属性来进行组件中的数据传递,这种模式是非常脆弱的。
- 在日常的开发中经常会遇到非父子组件传递的场景。原来的方式是找到共同的父级进行数据交互,这时通信就变得比较麻烦 我们先通过一个简单的例子实现一下redux的工作模式:
二、Redux原理(逐句解析)
- 1、这里我们可以将 renderContent,renderTitle看成两个组件通过一个函数 renderApp将相关的数据统一进行管理。
function renderTitle(title,oldTitle={}){
if(title === oldTitle)return;
let ele = document.getElementById('title');
ele.style.color = title.color;
ele.innerHTML = title.text;
}
function renderContent(content,oldContent={}){
if(content === oldContent)return;
let ele = document.getElementById('content');
ele.style.color = content.color;
ele.innerHTML = content.text;
}
function renderApp(appState,oldAppState={}) {
if(appState === oldAppState)return;
renderTitle(appState.title,oldAppState.title);
renderContent(appState.content,oldAppState.conent)
}
- 2、我们将最新状态放到了createStore函数中,生成 dispatch函数,操作 state,触发视图更新。
function createStore(reducer){
<-- 给 state一个为 null的初始值 -->
let state;
<-- 创建一个放置事件的事件池(数组) -->
const listener = [];
<-- 这个函数负责向事件池中添加事件; -->
const subscribe = (f)=>listener.push(f);
<-- 这个函数负责获取当前 state值,创造一份和状态同样的对象给外界来用 -->
const getState = ()=>{return state};
<-- 获取旧的 state值 -->
let oldState = state;
<-- 这个函数负责获取当前用户传输的 action实参 -->
const dispatch = (action)=>{
<-- 获取曾经还未覆盖的 state值 -->
oldState = state;
<-- 获取当前 state值覆盖掉旧的 state值 -->
state = reducer(state,action);
<-- 更新完成之后 重新渲染,把 state上一次旧的值 oldState添加到事件池 -->
listener.forEach(item => item && item(oldState));
}
<-- 默认传入空对象获取reducer返回的默认结果,为了初始化数据 -->
dispatch({})
return {
getState,
dispatch,
subscribe,
listener
}
}
- 3、使用 reducer方法进行状态的更改,派发一个带有type的属性来进行状态的更改,来获取 state的最新值reducer应该具有默认状态,当更改状态后使用最新的状态。
function reducer(state,action){
<-- 当循环上下文未找到 start相应的值时,给予 start的一个初始的默认状态 -->
if(!state){
return {
title:{
text:'标题',
color:"red"
},
content:{
text:"内容",
color:'blue'
}
}
}
<-- 依据 type的属性,对 state的状态进行更改 -->
switch(action.type){
case "UPDATE_TITLE":
// state.title.text = action.text;
return {
...state,
<-- 当前 title覆盖上一行 state中的state.title -->
title:{
...state.title,
<-- 当前 text覆盖上一行 state.title中的state.title.text -->
text:action.text,
}
}
break;
case "UPDATE_CONTENT":
// state.content.text = action.text;
return {
...state,
<-- 当前 content覆盖上一行 state中的state.content -->
content:{
...state.content,
<-- 当前 text覆盖上一行 state.title中的state.title.content -->
text:action.text,
}
}
break;
default:
<-- 若以上 case判断条件不符,则返回原来的 state -->
return state
break;
}
}
- 4、向相关函数传输实参,拿到相关函数执行后,返回的数据,触发视图更新
<-- 拿到createStore中返回的对象 -->
const store = createStore(reducer);
<-- 更新完成之后 重新渲染,把 state上一次旧的值 oldState添加到事件池 -->
store.subscribe((oldState)=>{renderApp(store.getState(),oldState)});
<-- 这个事件负责把修改完内容后重新渲染一下,让数据修改完成之后 自动更新视图 -->
renderApp(store.getState());
<-- 向相关函数名及对应type值进行参数更新 -->
store.dispatch({type:"UPDATE_TITLE",text:"修改过的标题3"});
<-- 向相关函数名及对应type值进行参数更新 -->
store.dispatch({type:"UPDATE_CONTENT",text:"修改过的内容3"});