hi,你好!欢迎访问本站!登录
本站由网站地图腾讯云宝塔系统阿里云强势驱动
当前位置:首页 - 教程 - 杂谈 - 正文 君子好学,自强不息!

Redux的中心观点,完成代码与运用示例

2019-11-18杂谈搜奇网22°c
A+ A-

Redux是一种JavaScript的状况治理容器,是一个自力的状况治理库,可合营别的框架运用,比方React。引入Redux重要为了使JavaScript中数据治理的轻易,易追踪,防止在大型的JavaScript运用中数据状况的运用杂沓状况。Redux 试图让 state 的变化变得可展望,为此做了一些行动限定商定,这些限定前提反映在 Redux 的三大准绳中。

本文会引见Redux的几个基本观点和对峙的三大准绳,以及完全的回路一下Redux中的数据流。在相识以上这些观点以后,用本身的代码来完成一个简版的Redux,而且用本身完成的Redux连系React框架,做一个简朴的TodoList运用示例。愿望本文关于初识Redux的同砚有一个清楚,周全的熟习。

Redux的几个基本观点

一、数据存储 - state

Redux就是用来治理状况数据,所以第一个观点就是状况数据,state就是寄存数据的处所,依据运用须要,平常定义成一个对象,比方:

{
    todos: [],
    showType: 'ALL',
    lastUpdate: '2019-10-30 11:56:11'
}

 

二、行动触发 - action

web运用,一切的数据状况变动,都是由一个行动触发的,比方用户点击,收集加载完成,或许定时事宜。在简朴运用内里,我们平常都是在行动触发的时刻,直接修正对应的数据状况,但是在大型庞杂的运用内里,修正统一数据的处所能够许多,每一个处所直接修正,会形成数据状况不可保护。

Redux引入了action的观点,每一个要转变数据状况的行动,都定义成一个action对象,用一个type来标志是什么行动,行动附带的数据,也都直接放在action对象,比方一个用户输入的行动:

{
    type: 'INPUT_TEXT',
    text: '今天下午6点运动见面集会'
}

然后经由过程dispatch触发这个action,dispatch(action)

三、行动响应 - reducer

状况,action的观点相识了,当action触发的时刻,肯定要修正state数据,在解说action的时刻有说过,不能直接修正state,我们须要定义一个reducer来修正数据,这个reducer就是一个行动响应函数,他吸收当前state,和对应的action对象,依据差别的action,做响应的逻辑推断和数据处置惩罚,然后返回一个新的state。

注重,肯定是返回一个新的state,不能直接修正参数传入的原state,这是redux的准绳之一,背面会讲到。

function reducer ( state = [], action ) {
    switch ( action.type ) {
        case 'INPUT_TEXT':
            return [...state, {text: action.text, id: Math.random() }]
        default:
            return state;
    }
}

 

四、数据监听 - subscribe

数据的更新已在reducer中完成了,在一些响应式的web运用中,我们每每须要监听数据状况的变化,这个时刻就能够用subscribe了

redux内部保留一个监听行列,listeners,能够挪用subscribe交游listeners内里增添新的监听函数,每次reducer修正完state以后,会逐一实行监听函数,而监听函数能够猎取已更新过的state数据了

listeners = [];
subscrible( listener ) {
    listeners.push( listener );
    return function () {
        let index = listeners.index( listener );
        listeners.splice( index, 1 );
    }
}
dispatch( action ) // 触发 action
reducer(state, action)

listeners.map( ( listener ) => {
    listener()
} )

 

Redux的几大准绳

一、单一数据准绳

悉数运用的数据都在state,而且只要这一个state,这么做的目标是轻易治理,悉数运用的数据就这一份,调试轻易,开辟也轻易,能够在开辟的时刻用当地的数据。而且开辟同构运用也很轻易,比方服务端衬着,把服务端的数据悉数放在state,作为web端初始化时刻的数据

二、state只读

state的数据对外只读,不能直接修正state,唯一能够修正的体式格局是触发action,然后经由过程reducer来处置惩罚。

因为一切的修正都被集中化处置惩罚,且严厉根据一个接一个的递次实行,因而不必忧郁竞态前提(race condition)的涌现。 Action 就是一般对象罢了,因而它们能够被日记打印、序列化、贮存、后期调试或测试时回放出来。

三、运用纯函数

先申明下什么是纯函数,纯函数指的是函数内部不修正传入的参数,无副作用,在传参肯定的状况下,返回的效果也是肯定的。Redux中的Reducer须要设想成存函数,不能直接操纵传入的state,须要把转变的数据以一个新的state体式格局返回。

Redux中的数据流

实在上面讲Redux基本观点的时刻已也许的说了下数据流向体式格局了,就是: view->action->reducer->state->view,用笔墨来表述就是,起首因为页面上的某些事宜会触发action,经由过程dispatch(action)来完成,然后经由过程reducer处置惩罚,reducer(state, action)返回一个新的state,完成state的更新,固然关于响应式的运用,会触发listener(),在listener内里猎取最新的state状况,完成对应视图(view)的更新。这就是悉数redux中的数据流形貌,以下图所示:

Redux的完成代码(非官方)

在对Redux的基本观点和几大准绳熟习了以后,能够完成一个本身的Redux了,固然我们平常都直接用官方的npm包,这里本身完成的比较简朴,没有做什么入参考证,非常处置惩罚之类的,重如果加深下对Redux的明白。下面直接贴代码了,对应的观点都有解释。

// redux.js
// 建立state的函数
// 传入reducer 和初始化的state
function createStore( reducer, initState ) {
    let ref = {};
    let listeners = [];
    let currentState = initState;

    // dispath函数,用来触发action
    function dispatch ( action ) {
        // 触发的action,经由过程reducer处置惩罚
        currentState = reducer( currentState, action )

        // 处置惩罚完成后,关照listeners
        for ( let i in listeners ) {
            let listener = listener[ i ];
            listener();
        }
        return action;
    }

    // 返回当前的state
    function getState () {
        return currentState;
    }

    // 定阅state变化, 传入listener,返回作废定阅的function
    function subscribe ( listener ) {
        listeners.push( listener );
        return function () {
            let index = listeners.indexOf( listener );
            if ( index > -1 ) {
                listeners.splice( index, 1 );
            }
        }
    }
    
    ref = {
        dispatch: dispatch,
        subscribe: subscribe,
        getState: getState
    };
    return ref;
}

function combineReducers( reducers ) {
    return function ( state, action ) {
        let finalState = {};
        let hasChanged = false;
        for ( let key in reducers ) {
            let reducer = reducers[ key ]
            if ( typeof reducer === 'function' ) {
                let keyState = reducer( state && state[ key ], action );
                hasChanged = hasChanged || keyState !== state[ key ];
                finalState[ key ] = keyState;
            }
        }
        return hasChanged ? finalState : state;
    }
}

export { createStore, combineReducers }

是否是以为怎样才这么点代码,就是这么点代码,而且还包括了一个combineReducers辅佐函数,下面再贴一点运用示例代码

// reducer函数,用于处置惩罚action
function reducer( state = [], action ) {
    switch( action.type ) {
        case 'INPUT_TEXT':
            return [ ...state, { text: action.text, key: Math.random(), isDo: false }];
        case 'TOGGLE_TODO':
            return state.map( ( item ) => {
                if ( item.key === action.id ) {
                    return {...item, isDo: !item.isDo };
                }
            } );
        default:
            return state;
    }
}

let store = createStore( reducer );

// 在用户输入一条Todo时刻
console.log(store.getState());
store.dispatch( { type: 'INPUT_TEXT', text: '这里是一条待办事项' } );
console.log(store.getState());

//在用户点击一条Todo Item的时刻,切换完成状况
console.log(store.getState());
store.dispatch( { type: 'TOGGLE_TODO', id: item.key } )
console.log(store.getState());

 

Redux与React的连系运用示例

下面,应用Redux连系React开辟一个简朴的Todo东西,页面重要功用点

1、能够增加Todo事项

2、点击事项会切换事项的完成状况

3、能够切换展现悉数/已完成/待完成事项

这个实例是基于react,react-redux完成的,项目搭建用的是create-react-app,应用react-redux供应的接口,将redux中的state和action集成到组件中,须要读者熟习create-react-app的运用,以及react-redux的重要接口功用,以下贴出重要代码,感兴趣的同砚能够本身搭建完成

起首定义好state数据结构和action以及对应的reducer

state包括两部份,一是todos,待办事项列表,二是showType,展现范例

action包括这么三种,一是增加新的Todo,二是切换事项完成状况,三是切换展现范例,离别定义好

actions.js

// actions.js
let nextTodoId = 0

export const addTodo = text => {
    return {
        type: 'ADD_TODO',
        id: nextTodoId++,
        text
    };
};

export const setShowType = showType => {
    return {
        type: "SET_SHOW_TYPE",
        showType
    };
};

export const toggleTodo = id => {
    return {
        type: 'TOGGLE_TODO',
        id
    };
};

reducers.js

const todos = ( state = [], action ) => {
    switch ( action.type ) {
        case 'ADD_TODO':
            return [
                ...state,
                {
                    id: action.id,
                    text: action.text,
                    isDo: false
                }
            ];
        case 'TOGGLE_TODO':
            return state.map( todo => {
                return todo.id === action.id ? {...todo, isDo: !todo.isDo } : todo;
            } );
        default:
            return state;
    }
}

const showType = ( state = 'SHOW_ALL', action ) => {
    switch ( action.type ) {
        case 'SET_SHOW_TYPE':
            return action.showType;
        default:
            return state;
    }
}

const todoList = combineReducers({
    todos,
    showType
})
export { todoList }

 

至此,数据状况redux部份算完成了,接下来完成对应的Component和进口文件了,预备分这么几个组件

1、待办事项Todo

2、输入框 AddTodo

3、待办事项列表TodoList

4、底部展现范例切换Tab

// component.js
import { connnect } from 'react-redux';
import { addTodo, setShowType, toggleTodo } from './actions'

const Todo = ( { onClick, completed, text } ) => (
    <li onClick={onClick} style={{ textDecoration: completed ? 'line-through' : 'none' }}>
        {text}
    </li>
)

const AddTodo = ( { dispatch } ) => {
    let input;
    return (
        <div>
            <form
                onSubmit={ e => {
                    e.preventDefault()
                    if ( !input.value.trim() ) {
                        return;
                    }
                    dispatch( addTodo( input.value ) )
                    input.value = ''
                }}
            >
                <input ref={ node => {input = node } } />
                <button type='submit'>Add Todo</button>
            </form>
        </div>
    )
}
AddTodo = connect()( AddTodo );

const TodoList =  ( { todos, onTodoClick } ) => {
    return (
        <ul>
            {todos.map( todo => (
                <Todo key={todo.id} {...todo} onClick={ () => onTodoClick( todo.id ) } />
            ) )}
        </ul>
    ) };
    
const getShowTodoList = ( todos, showType ) => {
    switch( showType ) {
        case 'SHOW_ISDO':
            return todos.filter( item => item.isDo );
        case 'SHOW_ACTIVE':
            return todos.filter( item => !item.isDo );
        case 'SHOW_ALL':
        default :
            return todos;
    }
}

const mapStateToProps = state => {
    return {
        todos: getShowTodoList ( state.todos, state.showType)
    };
};

const mapDispatchToProps = dispatch => {
    return {
        onTodoClick: id => {
            dispatch( toggleTodo( id ) );
        }
    };
}

const ShowTodoList = connect(
    mapStateToProps,
    mapDispatchToProps
)( TodoList );
   
 const Tab = () => (
    <p>
        Show: { ' ' }
        <FilterLink filter='SHOW_ALL'>ALL</FilterLink>
        { ', ' }
        <FilterLink filter='SHOW_ACTIVE'>ACTIVE</FilterLink>
        { ', ' }
        <FilterLink filter='SHOW_ISDO'>ISDO</FilterLink>
    </p>
)

export { AddTodo, ShowTodoList, Tab }

 

进口文件 index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from './redux';
import todoList from './reducers'
import {AddTodo, ShowTodoList, Tab } from './component'

let store = createStore( todoApp );

ReactDOM.render(
    <Provider store={store}>
        <div>
            <AddTodo />
            <ShowTodoList />
            <Tab />
        </div>
    </Provider>
    , document.getElementById('root'));

 

重要代码完成,npm start 运转,功用截图以下

文章同步宣布: https://www.geek-share.com/detail/2783420870.html

参考文章:

原生完成一个react-redux的代码示例

用React完成一个完全的TodoList的示例代码

  选择打赏方式
微信赞助

打赏

QQ钱包

打赏

支付宝赞助

打赏

  移步手机端
Redux的中心观点,完成代码与运用示例

1、打开你手机的二维码扫描APP
2、扫描左则的二维码
3、点击扫描获得的网址
4、可以在手机端阅读此文章
未定义标签

本文来源:搜奇网

本文地址:https://www.sou7.cn/281996.html

关注我们:微信搜索“搜奇网”添加我为好友

版权声明: 本文仅代表作者个人观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。请记住本站网址https://www.sou7.cn/搜奇网。

发表评论

选填

必填

必填

选填

请拖动滑块解锁
>>