从 0 到 1 理解 React redux 的设计思想 (5步分解, 保证小白都能看得懂)

栏目: IOS · Android · 发布时间: 4年前

内容简介:把之前学习redux的手写学习笔记分享出来一下,方便大家理解redux思想,毕竟前端工程师里面都说,这个是将redux思想的一个拆分, 将 redux 拆分成 5 部分,最终拼成一个react redux,有了redux之后 state不再是谁都可以任意调用setState修改的数据了,

把之前学习redux的手写学习笔记分享出来一下,方便大家理解redux思想,毕竟前端工程师里面都说,

初级前端和中级前端的区别就是是否懂 设计模式 和面向对象

这个是将redux思想的一个拆分, 将 redux 拆分成 5 部分,最终拼成一个react redux,

为什么使用react redux ?

有了redux之后 state不再是谁都可以任意调用setState修改的数据了,

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());
复制代码

以上所述就是小编给大家介绍的《从 0 到 1 理解 React redux 的设计思想 (5步分解, 保证小白都能看得懂)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Ajax模式与最佳实践

Ajax模式与最佳实践

Christian Gross / 李锟、张祖良、蔡毅、赵泽欣 / 电子工业出版社 / 2007-3 / 49.80元

Ajax 正在将我们带入到下一代的网络应用中。 本书深入探讨了动态的网络应用,将Ajax和REST集成在一起作为单独的解决方案。一个很大的优势是,与Ajax相似,REST可以和现今存在的技术一起使用。现在上百万的客户端计算机都是基于Ajax的,上百万的服务器是基于REST的。   无论你是否已经开发过Ajax应用程序,这都是一本理想的书。因为这本书描述了各种各样的模式和最好的实践经验。通过此......一起来看看 《Ajax模式与最佳实践》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试