把之前学习redux的手写学习笔记分享出来一下,方便大家理解redux思想,毕竟前端工程师里面都说,
初级前端和中级前端的区别就是是否懂设计模式和面向对象
这个是将redux思想的一个拆分, 将 redux 拆分成 5 部分,最终拼成一个react redux,
为什么使用react redux ?
有了redux之后 state不再是谁都可以任意调用setState修改的数据了,
react没有redux 和 有redux的核心区别**
react: 通过 setState修改state数据,再执行渲染;
react-redux: 通过 dispatch来判断是否执行setState,dispatch检测通过,执行setState函数, 否则不予执行;
1. 引入dispatch管理对setState的调用
<div id="title"></div>
<div id="contents"></div>
<script>
// 渲染模块
function render() {
document.getElementById('title').innerHTML = state.title;
document.getElementById('contents').innerHTML = state.content;
}
//数据模块
var state = {
title: '新的标题',
content: '新的内容'
}
//初次渲染执行
render();
//更改数据模块 ** 更改后触发数据渲染
function setState(newState) {
this.state = {
...state,
...newState
}
render()
}
</script>
复制代码
下面这部分是redux思想的和体现方式, 通过dispath判断参数的type是否合法, 合法才可以可以调用setState
<script>
// 管理模块, 想要触发数据改变请执行这个函数, 并且要给指定的type, 否则不执行setState
var dispatch = function (action) {
switch (action.type) {
case 'CHANGE_TITLE': // 传过来的type正确才能setState
setState({
title: action.newTitle
})
break;
default:
break;
}
}
//修改数据调用dispatch函数, 只有里面的json的type经过了dispatch检测才能执行相应的setState
dispatch(
{
type: 'CHANGE_TITLE',
newTitle: '我是经过dispatch函数允许修改后的新标题'
}
)
</script>
复制代码
2. 引入subscriber
<div id="title"></div>
<div id="contents"></div>
<script>
function render() {
document.getElementById('title').innerHTML = state.title;
document.getElementById('contents').innerHTML = state.content;
}
var state = {
title: '新的标题',
content: '新的内容'
}
render()
复制代码
创建数组listeners, 引入订阅subscriber 函数,该函数向数组中订阅(push)新的事件,比如render渲染函数,在成功触发setState后,会对listensers数组里面的函数依次执行。
var dispatch = function (action) {
switch (action.type) {
case 'CHANGE_TITLE':
state = {
...state,
title:action.newTitle
}
break;
default:
break;
}
listeners.forEach(e=>e()) //依次执行数组中订阅的事件
}
var listeners = []; //这个数组放setState之后执行的事件,
var subscribe = function(listener){ //用subscriber函数把事件push到事件数组中
listeners.push(listener)
}
subscribe(render) // 数组中放入render函数
dispatch(
{
type: 'CHANGE_TITLE',
newTitle: '我是经过dispatch函数允许修改后的新标题'
}
)
</script>
</body>
复制代码
3. 初步封装 createStore
div id="title"></div>
<div id="contents"></div>
<script>
//渲染函数
function render(state) {
document.getElementById('title').innerHTML = state.title;
document.getElementById('contents').innerHTML = state.content;
}
//store 核心部分
var createStore = function () {
//state数据
var state = {
title: '这是一个标题',
content: '这是一段内容'
}
//执行函数仓库
var listeners = [];
//获取state数据
var getState = function () {
return state;
}
//dispatch监控 type是否合法,合法才触发setState函数
var dispatch = function (action) {
switch (action.type) {
case 'CHANGE_TITLE':
state = {
...state,
title: action.newTitle
}
break;
default:
break;
}
listeners.forEach(e => e())
}
//事件订阅函数
var subscribe = function (listener) {
listeners.push(listener)
}
// 暴露调用接口
return {
dispatch,
subscribe,
getState
}
}
//调用部分
//创建实例化对象
var store = createStore();
//解构获取三个接口函数
var { subscribe, dispatch, getState } = store;
//订阅事件
subscribe(() => render(getState()));
//请求dispatch改变状态
dispatch(
{
type: 'CHANGE_TITLE',
newTitle: '我是经过dispatch函数允许修改后的新标题'
}
)
render(getState())
</script>
复制代码
但是这个createStore函数存在不纯的问题,含有定好的state 和 dispatch,接下来就是对该函数进行提纯处理。
4. createStore函数提纯处理,让createStore 和 state,setState相分离 , 将state和setState放入appReducer函数中
<div id="title"></div>
<div id="contents"></div>
<script>
//store 核心部分
var createStore = function () {
// 将state设置为 null;
var state = null
var listeners = [];
var dispatch = function (action) {
//调用dispatch时, 执行appReducer做判断
state = appReducer(state, action);
listeners.forEach(e => e());
}
//调用dispatch初始化state,获取appReducer中的默认state。
dispatch({})
var subscribe = function (listener) {
listeners.push(listener)
}
var getState = function () {
return state;
}
//暴露接口
return {
dispatch,
subscribe,
getState
}
}
var appReducer = function (state, action) {
//初始化store中的state
//因为state初始值为null
if (!state) {
return {
title: '这是一个标题',
content: '这是一段内容'
}
}
//更新state
switch (action.type) {
case 'CHANGE_TITLE':
return {
...state,
title: action.newTitle
}
break;
default:
return state;
}
}
var store = createStore();
var { subscribe, dispatch, getState } = store;
subscribe(() => render(getState()))
dispatch(
{
type: 'CHANGE_TITLE',
newTitle: '我是经过dispatch函数允许修改后的新标题'
}
)
function render(state) {
document.getElementById('title').innerHTML = state.title;
document.getElementById('contents').innerHTML = state.content;
}
//调用部分
render(getState())
</script>
复制代码
此时 createStore依然不是一个纯函数, 依然无法独立, 因为里面有写死的appReducer函数的执行;
5. 彻底让createStore变成纯构造函数 , appReducer作为参数传入到createStore。
// 现在已经是非常干净的纯构造函数了
function createStore(appReducer) {
state = null;
var listeners = [];
function dispatch(action) {
state = appReducer(state, action)
listeners.map(e => e())
}
dispatch({})
function getState() {
return state
}
function subscribe(listener) {
listeners.push(listener);
}
return {
dispatch,
getState,
subscribe
}
}
// appReucer 函数
function appReducer(state, action) {
//初始化数据
if (!state) {
return {
title: '你好',
content: '欢迎光临'
}
}
switch (action.type) {
case 'CHANGE_TITLE':
return {
...state,
title: action.newTitle
}
break;
default:
break;
}
}
//使用createStore部分
var store = createStore(appReducer);
var { dispatch,
getState,
subscribe } = store;
subscribe(() => render(getState()))
dispatch(
{
type: "CHANGE_TITLE",
newTitle: '我是经过dispatch函数允许修改后的新标题'
}
)
function render(state) {
document.getElementById('title').innerHTML = state.title;
document.getElementById('content').innerHTML = state.content;
}
render(getState());
复制代码
至此,react redux 核心思想已经搞定了,相信你一定看得懂。
作者:liyuanzhe-cn
链接:https://juejin.im/post/5cd2e9296fb9a031f0381391
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。