redux入门示例续

    前面一篇介绍了利用redux框架来实现计数器的例子,了解了redux设计思想,他将ui响应与数据更改分离,集中处理状态变更,然后渲染到页面,当有用户操作的时候,ui响应不会立即修改状态树,而是发出一个修改的指令dispatch,告诉store,要如何修改。在指令发出的同时,会指定action.type,如果有参数,还会配置在action对象中,如action.color='blue'。最终action={type:'CHANGE_COLOR',color:'blue'},当store接收了指令,会让reducer去处理:reducer根据action.type来决定如何修改state,会根据先前的state,计算出一个新的state。当状态树修改完毕,需要将修改的结果反映在页面上,这时候就需要调用页面渲染的方法。因此,在store内部会维护页面渲染的监听。页面渲染的时候,会获取store中的状态值,将结果显示在页面上,因此store还需要对外提供一个getState()的方法。包括dispatch指令,也算是store的方法。

    我们可以得出这样的结论:store提供getState,dispatch,subscribe方法来完成这些操作。而store就好比整个操作的核心,他掌管着系统中的一切。

    因为涉及到状态,而这个状态因为系统的复杂程度而定,因此store的思想是将每个组件对应的state交给外部来初始化,需要修改的时候,只需要知道之前的state即可。

    这里会给出一个原生实现的redux示例,来帮助我们理解redux的设计思想。我们的核心store需要这么来创建:

    function createStore(){
        let state;
        const getState = () => state
        const subscribe = () => {}
        const dispatch = (action) => {}
        return {
            getState,
            subscribe,
            dispatch
        }
    }

    这段代码基本包含了要实现redux设计思想的主要代码,另外,redux希望修改状态reducer不应该在createStore()中来实现,需要放在外部,因此,我们需要通过传参的形式将 reducer传递进来,然后在dispatch函数中调用。

    我们根据这个思路,编写一个简单的修改颜色的示例:

    index-redux.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>redux-totorial</title>
    <style>
        *{margin:0;padding:0}
        h2{padding:20px 0;}
        button{padding:5px;border-radius:2px;border:1px solid #ccc;outline:none;cursor: pointer;color:#fff;}
        #root{margin:0 auto;width:1000px;}
        #btn-blue{background:blue;border-color:blue;}
        #btn-green{background:green;border-color:green;}
    </style>
</head>
<body>
    <div id="root">
        <h2 id="content">hello,redux.</h2>
        <div>
            <button id="btn-blue">blue</button id="btn-blue">
            <button id="btn-green">green</button>
        </div>
    </div>
    <script type="text/javascript">
        const $ = (id) => document.getElementById(id)
        const render = () => {
            $('content').style.color = store.getState().color
        }
        const initState = {
            color:'blue'
        }
        function reducer(state=initState,action){
            switch(action.type){
                case 'CHANGE_COLOR':
                    return {
                        ...state,
                        color:action.color
                    }
                default:
                    return state
            }
        }
        function createStore(reducer){
            let state;
            let listeners = []
            const subscribe = (ln) => {
                listeners.push(ln)
                const unsubscribe = () => {
                    listeners = listeners.filter(listener => ln!=listener);
                }
                return unsubscribe
            }
            const getState = () => state;
            const dispatch = (action) => {
                state = reducer(state,action)
                listeners.forEach(ln => ln())
            }
            dispatch({type:'xxx'})
            return {
                getState,
                subscribe,
                dispatch
            }
        }
        const store = createStore(reducer)
        render()
        store.subscribe(render)
        $('btn-blue').onclick = function(e){
            store.dispatch({type:'CHANGE_COLOR',color:'blue'})
        }

        $('btn-green').onclick = function(e){
            store.dispatch({type:'CHANGE_COLOR',color:'green'})
        }
        
    </script>
</body>
</html>

    打开页面,h2标签的文字会显示蓝色,当我们点击两个按钮进行设置的时候,会分别显示蓝色和绿色。

   

    

    示例很简单,但是思路很重要,初始状态,我们会在createStore外面声明:

   

    reducer函数会根据初始状态和action的参数type判断该如何修改状态,并返回新的状态:

   

    render函数就是我们的渲染函数,他会被store监听,并且在dispatch执行完成之后,被调用,达到渲染的目的:

   

    

    最重要的是store的创建函数,包含了getState,subscribe,dispatch三个主要的方法:

       

    dispatch指令就是在ui响应的时候发出,只管发指令,不管如何修改以及修改之后的渲染:

   

    如何修改交给reducer去做,修改之后的渲染是交给subscribe的订阅函数render去做的。

发布了529 篇原创文章 · 获赞 287 · 访问量 147万+

猜你喜欢

转载自blog.csdn.net/feinifi/article/details/103733647
今日推荐