React 手写redux原理

手写Redux

html文档

<!DOCTYPE html>
<html >
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="root">
        <div id="title"></div>
        <div id="content">0</div>
    </div>
<script src="./redux-my.js"></script>


</body>
</html>

过程1

//redux 状态管理 把数据集中存放
//当前所有组件的状态
let state = {
    title:{content:'你好',color:'red'},
    content:{content:'哈哈',color:'green'}
}
function renderTitle() {
    let title = document.getElementById('title');
    title.innerHTML = state.title.content;
    title.style.background = state.title.color;
}
function renderContent() {
    let content = document.getElementById('content');
    content.innerHTML = state.content.content;
    content.style.background = state.content.color;
}
function renderApp(){
    renderTitle();
    renderContent();
}
renderApp();

过程2

//redux 状态管理 把数据集中存放
//当前所有组件的状态
// 上面的版本中 状态会被更改,任何组件都可以修改,这样会影响我们所有的代码,对其进行封闭
//这里还是可以改状态的
function createStore(){
    let state = {
        title:{content:'你好',color:'red'},
        content:{content:'哈哈',color:'green'}
    }
    let getState = ()=>state;
    return {
        getState
    }
}
let store = createStore()

//1.redux中不能直接操作状态
function renderTitle() {
    let title = document.getElementById('title');
    title.innerHTML = store.getState().title.content;
    title.style.background = store.getState().title.color;
}
function renderContent() {
    let content = document.getElementById('content');
    content.innerHTML = store.getState().content.content;
    content.style.background = store.getState().content.color;
}
function renderApp(){
    renderTitle();
    renderContent();
}
renderApp();

过程3:

//redux 状态管理 把数据集中存放
//当前所有组件的状态
// 上面的版本中 状态会被更改,任何组件都可以修改,这样会影响我们所有的代码,对其进行封闭
function createStore(){
    let state = {
        title:{content:'你好',color:'red'},
        content:{content:'哈哈',color:'green'}
    }
    let getState = ()=>JSON.parse(JSON.stringify(state)); //返回拷贝对象
    return {
        getState
    }
}
let store = createStore()

//1.redux中不能直接操作状态
function renderTitle() {
    let title = document.getElementById('title');
    title.innerHTML = store.getState().title.content;
    title.style.background = store.getState().title.color;
}
function renderContent() {
    let content = document.getElementById('content');
    content.innerHTML = store.getState().content.content;
    content.style.background = store.getState().content.color;
}
function renderApp(){
    renderTitle();
    renderContent();
}
renderApp();

过程4

//redux 状态管理 把数据集中存放
//当前所有组件的状态
// 上面的版本中 状态会被更改,任何组件都可以修改,这样会影响我们所有的代码,对其进行封闭

function createStore(){
    let state = {
        title:{content:'你好',color:'red'},
        content:{content:'哈哈',color:'green'}
    }
    let getState = ()=>JSON.parse(JSON.stringify(state)); //返回拷贝对象
    let dispatch = (action)=>{
        switch (action.type) {
            case 'CHANGE_TITLE_COLOR':
                    console.log(action.color)
                    state.title.color = action.color;
                break;
        }
    }
    return {
        getState,
        dispatch
    }
}
let store = createStore()
setTimeout(function () {
    store.dispatch({type:'CHANGE_TITLE_COLOR',color:'pink'})
    renderApp()
},1000)

//1.redux中不能直接操作状态
//2.如果任意一个组件中想更新状态,需要派发一个动作 dispatch 实现状态更新的 方法
function renderTitle() {
    let title = document.getElementById('title');
    title.innerHTML = store.getState().title.content;
    title.style.background = store.getState().title.color;
}
function renderContent() {
    let content = document.getElementById('content');
    content.innerHTML = store.getState().content.content;
    content.style.background = store.getState().content.color;
}
function renderApp(){
    renderTitle();
    renderContent();
}
renderApp();

过程5:

//redux 状态管理 把数据集中存放
//当前所有组件的状态
// 上面的版本中 状态会被更改,任何组件都可以修改,这样会影响我们所有的代码,对其进行封闭

function createStore(){
    let state = {
        title:{content:'你好',color:'red'},
        content:{content:'哈哈',color:'green'}
    }
    let getState = ()=>JSON.parse(JSON.stringify(state)); //返回拷贝对象
    let dispatch = (action)=>{
        switch (action.type) {
            case 'CHANGE_TITLE_COLOR':
                    console.log(action.color)
                    state.title.color = action.color;
                break;
        }
    }
    return {
        getState,
        dispatch
    }
}
let store = createStore()
setTimeout(function () {
    store.dispatch({type:'CHANGE_TITLE_COLOR',color:'pink'})
    renderApp()
},1000)

//1.redux中不能直接操作状态
//2.如果任意一个组件中想更新状态,需要派发一个动作 dispatch 实现状态更新的 方法
function renderTitle() {
    let title = document.getElementById('title');
    title.innerHTML = store.getState().title.content;
    title.style.background = store.getState().title.color;
}
function renderContent() {
    let content = document.getElementById('content');
    content.innerHTML = store.getState().content.content;
    content.style.background = store.getState().content.color;
}
function renderApp(){
    renderTitle();
    renderContent();
}
renderApp();

过程6:

//redux 状态管理 把数据集中存放
//当前所有组件的状态
// 上面的版本中 状态会被更改,任何组件都可以修改,这样会影响我们所有的代码,对其进行封闭
let initstate = {
    title:{content:'你好',color:'red'},
    content:{content:'哈哈',color:'green'}
}
function createStore(reducer){
    let state;
    let getState = ()=>{return JSON.parse(JSON.stringify(state))}; //返回拷贝对象
    let dispatch = (action)=>{
        state = reducer(state,action)
    }
    dispatch({type:'@INIT'})
    return {
        getState,
        dispatch
    }
}
function reducer(state=initstate,action){
    switch (action.type) {
        case 'CHANGE_TITLE_COLOR':
            console.log(action.color)
            //不要直接修改
            //state.title.color = action.color;
            return {...state,title: {...state.title,color:action.color}}
            break;

    }
    return state;
    //return initstate;
}
let store = createStore(reducer)

setTimeout(function () {
    store.dispatch({type:'CHANGE_TITLE_COLOR',color:'pink'})
    renderApp()
},1000)

//1.redux中不能直接操作状态
//2.如果任意一个组件中想更新状态,需要派发一个动作 dispatch 实现状态更新的方法
//3.中间有个状态缺失,reducer。为什么要有这个环节?我想复用createStore();逻辑都写在这里面那么导致,原文件会被不断的修改,需要将 用户的数据提取出来。
//4.每次更新状态,最好用一个新的状态对象覆盖掉,每次状态改了,记录一下,可以对比一下。,如果直接修改那它引用一样,对比就没有了。
function renderTitle() {
    let title = document.getElementById('title');
    title.innerHTML = store.getState().title.content;
    title.style.background = store.getState().title.color;
}
function renderContent() {
    let content = document.getElementById('content');
    content.innerHTML = store.getState().content.content;
    content.style.background = store.getState().content.color;
}
function renderApp(){
    renderTitle();
    renderContent();
}
renderApp();

过程7

//redux 状态管理 把数据集中存放
//当前所有组件的状态
// 上面的版本中 状态会被更改,任何组件都可以修改,这样会影响我们所有的代码,对其进行封闭
let initstate = {
    title:{content:'你好',color:'red'},
    content:{content:'哈哈',color:'green'}
}
function createStore(reducer){
    let state;
    let getState = ()=>{return JSON.parse(JSON.stringify(state))}; //返回拷贝对象
    let dispatch = (action)=>{
        state = reducer(state,action)
    }
    dispatch({type:'@INIT'})
    return {
        getState,
        dispatch
    }
}
function reducer(state=initstate,action){
    switch (action.type) {
        case 'CHANGE_TITLE_COLOR':
            console.log(action.color)
            //不要直接修改
            //state.title.color = action.color;
            return {...state,title: {...state.title,color:action.color}}
        case 'CHANGE_CONOTENT_CONTENT':
            console.log(action.content)
            //不要直接修改
            //state.title.color = action.color;
            return {...state,content: {...state.content,content:action.content}}
    }
    return state;
    //return initstate;
}
let store = createStore(reducer)

setTimeout(function () {
    store.dispatch({type:'CHANGE_TITLE_COLOR',color:'pink'})
    store.dispatch({type:'CHANGE_CONOTENT_CONTENT',content:'这是新值'})
    renderApp()
},1000)

//1.redux中不能直接操作状态
//2.如果任意一个组件中想更新状态,需要派发一个动作 dispatch 实现状态更新的方法
//3.中间有个状态缺失,reducer。为什么要有这个环节?我想复用createStore();逻辑都写在这里面那么导致,原文件会被不断的修改,需要将 用户的数据提取出来。
//4.每次更新状态,最好用一个新的状态对象覆盖掉,每次状态改了,记录一下,可以对比一下。,如果直接修改那它引用一样,对比就没有了。
function renderTitle() {
    let title = document.getElementById('title');
    title.innerHTML = store.getState().title.content;
    title.style.background = store.getState().title.color;
}
function renderContent() {
    let content = document.getElementById('content');
    content.innerHTML = store.getState().content.content;
    content.style.background = store.getState().content.color;
}
function renderApp(){
    renderTitle();
    renderContent();
}
renderApp();

过程8

//redux 状态管理 把数据集中存放
//当前所有组件的状态
// 上面的版本中 状态会被更改,任何组件都可以修改,这样会影响我们所有的代码,对其进行封闭
let initstate = {
    title:{content:'你好',color:'red'},
    content:{content:'哈哈',color:'green'}
}
function createStore(reducer){
    let state;
    let listeners = []
    let getState = ()=>{return JSON.parse(JSON.stringify(state))}; //返回拷贝对象
    let dispatch = (action)=>{
        state = reducer(state,action)
        listeners.forEach(item=>item());
    }

    let subscribe = (fn) =>{
        listeners.push(fn)

    }

    dispatch({type:'@INIT'})
    return {
        getState,
        dispatch,
        subscribe
    }
}
function reducer(state=initstate,action){
    switch (action.type) {
        case 'CHANGE_TITLE_COLOR':
            console.log(action.color)
            //不要直接修改
            //state.title.color = action.color;
            return {...state,title: {...state.title,color:action.color}}
        case 'CHANGE_CONOTENT_CONTENT':
            console.log(action.content)
            //不要直接修改
            //state.title.color = action.color;
            return {...state,content: {...state.content,content:action.content}}
    }
    return state;
    //return initstate;
}
let store = createStore(reducer)
store.subscribe(renderApp);
store.subscribe(()=>{console.log('呵呵')});
setTimeout(function () {
    store.dispatch({type:'CHANGE_TITLE_COLOR',color:'pink'})
},1000)
setTimeout(function () {

    store.dispatch({type:'CHANGE_CONOTENT_CONTENT',content:'这是新值'})
},2000)
//1.redux中不能直接操作状态
//2.如果任意一个组件中想更新状态,需要派发一个动作 dispatch 实现状态更新的方法
//3.中间有个状态缺失,reducer。为什么要有这个环节?我想复用createStore();逻辑都写在这里面那么导致,原文件会被不断的修改,需要将 用户的数据提取出来。
//4.每次更新状态,最好用一个新的状态对象覆盖掉,每次状态改了,记录一下,可以对比一下。,如果直接修改那它引用一样,对比就没有了。
//5.每次状态更新后,需要手动调用renderApp,通过订阅后,状态更改后自动触发

function renderTitle() {
    let title = document.getElementById('title');
    title.innerHTML = store.getState().title.content;
    title.style.background = store.getState().title.color;
}
function renderContent() {
    let content = document.getElementById('content');
    content.innerHTML = store.getState().content.content;
    content.style.background = store.getState().content.color;
}
function renderApp(){
    renderTitle();
    renderContent();
}
renderApp();

过程9

//redux 状态管理 把数据集中存放
//当前所有组件的状态
// 上面的版本中 状态会被更改,任何组件都可以修改,这样会影响我们所有的代码,对其进行封闭
let initstate = {
    title:{content:'你好',color:'red'},
    content:{content:'哈哈',color:'green'}
}
function createStore(reducer){
    let state;
    let listeners = []
    let getState = ()=>{return JSON.parse(JSON.stringify(state))}; //返回拷贝对象
    let dispatch = (action)=>{
        state = reducer(state,action)
        listeners.forEach(item=>item());
    }

    let subscribe = (fn) =>{
        listeners.push(fn)
        return ()=>{
            listeners = listeners.filter(l=>l!==fn);
        }
    }

    dispatch({type:'@INIT'})
    return {
        getState,
        dispatch,
        subscribe
    }
}
function reducer(state=initstate,action){
    switch (action.type) {
        case 'CHANGE_TITLE_COLOR':
            console.log(action.color)
            //不要直接修改
            //state.title.color = action.color;
            return {...state,title: {...state.title,color:action.color}}
        case 'CHANGE_CONOTENT_CONTENT':
            console.log(action.content)
            //不要直接修改
            //state.title.color = action.color;
            return {...state,content: {...state.content,content:action.content}}
    }
    return state;
    //return initstate;
}
let store = createStore(reducer)
store.subscribe(renderApp);
let unsub  = store.subscribe(()=>{console.log('呵呵')});

setTimeout(function () {
    store.dispatch({type:'CHANGE_TITLE_COLOR',color:'pink'})
},1000)
setTimeout(function () {
    unsub();
    store.dispatch({type:'CHANGE_CONOTENT_CONTENT',content:'这是新值'})
},2000)
//1.redux中不能直接操作状态
//2.如果任意一个组件中想更新状态,需要派发一个动作 dispatch 实现状态更新的方法
//3.中间有个状态缺失,reducer。为什么要有这个环节?我想复用createStore();逻辑都写在这里面那么导致,原文件会被不断的修改,需要将 用户的数据提取出来。
//4.每次更新状态,最好用一个新的状态对象覆盖掉,每次状态改了,记录一下,可以对比一下。,如果直接修改那它引用一样,对比就没有了。
//5.每次状态更新后,需要手动调用renderApp,通过订阅后,状态更改后自动触发
//6.隔2s我取消订阅,怎么做?
function renderTitle() {
    let title = document.getElementById('title');
    title.innerHTML = store.getState().title.content;
    title.style.background = store.getState().title.color;
}
function renderContent() {
    let content = document.getElementById('content');
    content.innerHTML = store.getState().content.content;
    content.style.background = store.getState().content.color;
}
function renderApp(){
    renderTitle();
    renderContent();
}
renderApp();

到此已经完成手写的过程,代码其实不难,难点就是我们对其的理解层面吧。

Redux中间件(redux-thunk)异步处理(ajax)

//actionCreators.js
export const getTodoList=(arr)=> {
    /*return ()=>{
        axios.get('http://localhost:3000/json/res.json')
            .then((data) => {
                const res = data.data;
                initListAction(res);
            })
    }*/
    return async ()=>{
        let res =await axios.get('http://localhost:3000/json/res.json')
        if(!res) return;
        initListAction(res.data)
    }
}
//TodoList组件修改生命周期
componentDidMount() {
    const action = actions.getTodoList();
    store.dispatch(action)
}

这样的话,我们将组件内部的功能全部拆分出去,并且这样也是为了将来让actions可以快速进行前端自动化测试。同样的我们发现我们可以使用async/await更易于管理代码。

react-redux(必须掌握)

修改入口文件

import React from 'react';
import {Provider} from 'react-redux'
import ReactDOM from 'react-dom';
import TodoList from './redux-update/TodoList'
import store from './redux-update/store/index.js'

ReactDOM.render(
    <Provider store={store}>
        <TodoList></TodoList>
    </Provider>
    , document.getElementById('root'));

修改TodoList组件

import React,{Component} from 'react';
import {connect} from 'react-redux';
 class TodoList extends Component{
    constructor(props){
        console.log(props)
        super(props);
        this.state = {}
    }

    render() {
        return (
            <div>
                <div>
                    <input onChange={this.props.Hchange.bind(this)} value={this.props.name} type="text"/>
                    <button>提交</button>
                </div>
                <ul>
                    <li>DELL</li>
                </ul>
            </div>
        );
    }
}
const mapStateToProps = (state)=>{
    return {
     name:state.name,
     list:state.list
    }
}
//发布store.dispatch, props
const mapDispatchToProps = (dispatch)=>{
     return {
         Hchange(e){
             const action = {
                 type:'change_input_value',
                 value:e.target.value
             }
             dispatch(action)
         }
     }
}

export default connect(mapStateToProps,mapDispatchToProps)(TodoList);

}store文件

import {createStore} from 'redux'

import reducer from './reducer'

const store = createStore(reducer);

export default  store;

reducer文件

let initData={
    name:'hello world',
    list:[]
}
//reducer
export default (state=initData,action)=>{
    if(action.type==='change_input_value'){
        var newvalue = JSON.parse(JSON.stringify(state))
        newvalue.name = action.value;
        return newvalue;
    }
    return initData;
}

在这里大家要建立几个概念。首先在入口文件中将store引入到整个组件中。其次在组件中通过connct来进行连接入口传递Provider的传来的store数据。

注意在组件最后导出时,export default connect(参数1,参数2)(参数3)

这里千万要注意导出的对象要进行连接。参数1,为数据集合,参数2为actions集合,参数3为我们当前的组件名称。

总结:

在这里面,其实都是有很多的概念,相较VueVuex确实挺绕,不过我们学习,就是这样,不断接受新的思想,也要和老的思想进行比较,到了最后位置我们可以发现我们的代码其实也不是很难,就是在理解基础上,有更新认识就会更好。在书写文章时,参才了太多的知识,感谢网络的力量。也感谢官方的支持。

文章参考:

https://www.jianshu.com/p/9baca3ca08fa

https://github.com/ruanyf/extremely-simple-flux-demo

https://redux.js.org/introduction/getting-started Redux入门

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容