刚开始接触到redux的时候, 对于redux中的概念, 只有一个store是知道的, 其他的都像是在阅读天书一样. 网上找了很多资料和文档来阅读, 也是通过多次的实践,慢慢的对于redux的概念一知半解, 想着如此就去阅读一下源码, 或许会有不一样的收获.于是就有了这篇文章
关于redux,
只需要记住它是一个状态管理器, 于react无关, 是一个独立的库 state: 表示状态 dispatch: 改变状态 reducer: 包含改变状态的数据 subscribe: 订阅state 中间件
我们来看看redux的核心是怎么改变数据的:
代码语言:txt复制let state = { name: 'liang' };
state.name = 'Tim';
这样是不是就实现了数据的改变了呢?!
估计这样会被读者打死o(╥﹏╥)o , 但是redux的核心就是这样的, 我们一步步展开来说。
上面的代码虽然实现了修改, 但是却没有通知到所有使用到name的地方上,我们通过发布订阅来实践一下
代码语言:txt复制let state = { name: 'liang' };
let listeners = [];
function subscribe(listener) {
listeners.push(listener);
};
function changeState(name) {
state.name = name;
for (let i = 0; i < listeners.length; i ) {
const listener = listeners[i];
listener();
}
}
/*-------我是分割线--------*/
//订阅state中的数据
subscribe(() => {
console.log(state.name);
});
changeState('小米'); //小米
changeState('小红'); //小红
上面的例子确实通过发布订阅实现了数据的改变时,通知到每个监听的地方,但是却有几个问题:
- 只能改变name,不通用
- 公共的代码应该封装起来
于是,我们尝试着将代码封装起来,形成一个可通用的代码。
代码语言:txt复制function createState(initState) {
let state = initState;
let listeners = [];
//订阅功能
function subscribe(listener) {
listeners.push(listener);
}
//改变状态的方法同时通知所有的订阅者
function changeState(newState) {
state = newState;
for(let i = 0; i < listeners.length; i ) {
const listener = listeners[i];
listener();
}
}
//获取状态
function getState() {
return state;
}
return { getState, changeState, subscribe };
}
我们使用上面的代码来试一下效果
代码语言:txt复制let initState = {
count: 1,
person: {
name: '小红',
sex: '女'
},
};
const store = createState(initState);
store.subscribe(() => {
let state = store.getState();
console.log(`名字:${state.person.name},性别:${state.person.sex}`);
});
store.subscribe(() => {
let state = store.getState();
console.log(state.count);
});
store.changeState({ ...store.getState(), count: 2 });
//名字:小红,性别:女
//2
store.changeState({ ...store.getState(), person: { name: '小明', sex: '男' } });
//名字:小明,性别:男
//2
这样我们就实现了一个简单的状态管理器了。
这时候是不是应该不要脸的鼓励自己,完成了redux的核心☺,但是这个仅仅只是个开始,我们目标当然是完成一个完整redux了,尽管不能媲美真正的redux(毕竟人家已经是老牌选手了),但是我们不能放弃造轮子的梦想。于是,我们重新来看这段代码,假设我们修改如下
代码语言:txt复制store.changeState({ ...store.getState(), count: 'abc' });
//名字:小明,性别:男
//abc
从结果来看,count的类型发生了改变,它可以被任意的修改,我们需要约束一下,更希望能够有计划的去改变,而上面的代码不能够支持这种能力,于是,我们扩展开来:
- 希望有个函数可以控制值的返回,我们叫它为handle吧
- 让store.changeState方法知道,告诉它修改state的时候,按我们的希望的修改
我们来实现handle函数,它接受一个老的state和一个包含改变state的对象,返回新的state
代码语言:txt复制function handle(state, action) {
switch(action.type) {
case 'INCREMENT':
return { ...state, count: state.count 1 };
case 'DECREMENT':
return { ...state, count: state.count - 1 };
default:
return state;
}
}
在我们的createState函数中增加handle函数
代码语言:txt复制function createState(handle, initState) {
let state = initState;
let listeners = [];
//订阅功能
function subscribe(listener) {
listeners.push(listener);
}
//通知
function changeState(action) {
//按我们期望的返回
state = handle(state, action);
for(let i = 0; i < listeners.length; i ) {
const listener = listeners[i];
listener();
}
}
function getState() {
return state;
}
return { getState, subscribe, changeState };
}
我们来尝试一下:
代码语言:txt复制let initState = { count: 0 };
const store = createState(handle, initState);
store.subscribe(() => {
console.log(store.getState().count);
});
store.changeState({ type: 'INCREMENT' }); //1
store.changeState({ type: 'DECREMENT' }); //0
store.changeState({ count: 'abc' }); //0
从结果来看,我们已经实现了我们的功能了,state可以按照我们期望的要求进行改变了,对count直接进行改变已经是没有效果了的。
到此为止,我们已经实现一个完整的状态管理器。这也是redux的核心之一。
现在,我们来商量一下,我们把名字改一下,把changeState改成dispatch,handle改成reducer,这样是不是感觉很厉害,很高大上的样子☺!!!毕竟reudx就是这样叫的,我们当然要向它学习了。
总结
- 利用发布订阅模式实现通知每个监听的地方
- 通过handle函数实现了有计划的控制返回的数据
redux肯定远远不止这些,如果想知道更多,请留意下回分解
详情传送门 : https://github.com/reduxjs/redux/tree/master/src