【前端丛林】React这样服用,效果更佳(15)

65 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第15天,点击查看活动详情

前言

哈喽大家好,我是Lotzinfly,一位前端小猎人。欢迎大家再次来到前端丛林,在这里你将会遇到各种各样的前端猎物,我希望可以把这些前端猎物统统拿下,嚼碎了服用,并成为自己身上的骨肉。今天是我们冒险的第十五天,昨天给大家介绍了一下Redux了解其基本概念和API,今天我们来介绍一下Redux的应用,看看Redux到底有哪些作用,让我们探寻其中的奥秘。话不多说,开始我们的冒险之旅吧!

1.原生计数器

首先我们用Redux来实现一个原生计数器

1.1 index.html

<div id="counter">
    <p id="counter-value">0</p>
    <button id="increment-btn">+</button>
    <button id="decrement-btn">-</button>
</div>

1.2 index.js

import { createStore } from 'redux';
let counterValue = document.getElementById('counter-value');
let incrementBtn = document.getElementById('increment-btn');
let decrementBtn = document.getElementById('decrement-btn');
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';
let initState = 0;
function reducer(state = initState, action) {
    switch (action.type) {
        case INCREMENT:
            return state + 1;
        case DECREMENT:
            return state - 1;
        default:
            return state;
    }
}
let store = createStore(reducer);
function render() {
    counterValue.innerHTML = store.getState();
}
store.subscribe(render);
render();
incrementBtn.addEventListener('click', function () {
    store.dispatch({ type: INCREMENT });
});
decrementBtn.addEventListener('click', function () {
    store.dispatch({ type: DECREMENT });
});

1.3 redux

1.3.1 index.js

src\redux\index.js

import createStore from './createStore'
  export {
    createStore
}

1.3.2 createStore.js

src\redux\createStore.js

export default function createStore(reducer, preloadedState) {
    let currentState = preloadedState;
    let currentListeners = [];
    function getState() {
        return currentState;
    }
    function subscribe(listener) {
        currentListeners.push(listener);
        return function unsubscribe() {
            const index = currentListeners.indexOf(listener);
            currentListeners.splice(index, 1);
        };
    }
    function dispatch(action) {
        if (Object.getPrototypeOf(action) !== Object.prototype) {
            throw new Error(`动作必须是一个纯对象,如果想进行异步操作请使用中间件`);
        }
        if (typeof action.type === "undefined") {
            throw new Error(`动作不能一个值为undefined的type属性`);
        }
        currentState = reducer(currentState, action);
        for (let i = 0; i < currentListeners.length; i++) {
            const listener = currentListeners[i];
            listener();
        }
        return action;
    }
    dispatch({ type: '@@redux/INIT' });
    return {
        dispatch,
        subscribe,
        getState
    };
}

2.React计数器

接着我们使用React实现一个计数器

import React, { Component } from 'react';
import { createStore } from '../redux';
function reducer(state = 0, action) {
    switch (action.type) {
        case 'INCREMENT':
            return state + 1;
        case 'DECREMENT':
            return state - 1;
        default:
            return state;
    }
}
const store = createStore(reducer, 0);
export default class Counter extends Component {
    constructor(props) {
        super(props);
        this.state = { value: 0 };
    }
    componentDidMount() {
        this.unsubscribe = store.subscribe(() => this.setState({
            value: store.getState()
        }));
    }
    componentWillUnmount() {
        this.unsubscribe();
    }
    render() {
        return (
            <div>
                <p>{this.state.value}</p>
                <button onClick={() => store.dispatch({ type: 'INCREMENT' })}>+</button>
                <button onClick={() => store.dispatch({ type: 'DECREMENT' })}>-</button>
                <button onClick={
                    () => {
                        setTimeout(() => {
                            store.dispatch({ type: 'INCREMENT' })
                        }, 1000);
                    }
                }>1秒后加1</button>
            </div>
        )
    }
}

3. bindActionCreators.js

把一个 value 为不同 action creator 的对象,转成拥有同名 key 的对象。同时使用 dispatch 对每个 action creator 进行包装,以便可以直接调用它们。

简单来讲,bindActionCreators的作用是将一个或多个action和dispatch组合起来生成mapDispatchToProps需要生成的内容。

通过传递两个参数:

(1) action 创建函数 或 action 创建函数的对象

(2) dispatch 函数

从而获得增强功能的 action 创建函数 或 action 创建函数的对象

3.1 Counter.js

import React, { Component } from 'react';
import { createStore, bindActionCreators } from '../redux';
function reducer(state = 0, action) {
    switch (action.type) {
        case 'INCREMENT':
            return state + 1;
        case 'DECREMENT':
            return state - 1;
        default:
            return state;
    }
}
const store = createStore(reducer, 0);
function increment() {
    return { type: 'INCREMENT' };
}
function decrement() {
    return { type: 'DECREMENT' };
}
const actions = { increment, decrement };
//const boundIncrement = bindActionCreators(increment,store.dispatch);//可以传一个函数
const boundActions = bindActionCreators(actions, store.dispatch);//也可以传对象
export default class Counter extends Component {
    constructor(props) {
        super(props);
        this.state = { value: 0 };
    }
    componentDidMount() {
        this.unsubscribe = store.subscribe(() => this.setState({
            value: store.getState()
        }));
    }
    componentWillUnmount() {
        this.unsubscribe();
    }
    render() {
        return (
            <div>
                <p>{this.state.value}</p>
                <button onClick={boundIncrement}>+</button>
                <button onClick={boundIncrement}>-</button>
            </div>
        )
    }
}

3.2 bindActionCreators.js

bindActionCreators.js

function bindActionCreator(actionCreator, dispatch) {
    return function () {
        return dispatch(actionCreator.apply(this, arguments))
    }
}
export default function bindActionCreators(actionCreators, dispatch) {
    if (typeof actionCreators === 'function') {
        return bindActionCreator(actionCreators, dispatch)
    }
    const boundActionCreators = {}
    for (const key in actionCreators) {
        const actionCreator = actionCreators[key]
        if (typeof actionCreator === 'function') {
            boundActionCreators[key] = bindActionCreator(actionCreator, dispatch)
        }
    }
    return boundActionCreators
}

结尾

好啦,这期的前端丛林大冒险先到这里啦!这期我们了解了Redux到底有哪些应用。这期内容要好好啃下来嚼烂嚼透。希望大家可以好好品尝并消化,迅速升级,接下来我们才更好地过五关斩六将!好啦,我们下期再见。拜拜!