持续创作,加速成长!这是我参与「掘金日新计划 · 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到底有哪些应用。这期内容要好好啃下来嚼烂嚼透。希望大家可以好好品尝并消化,迅速升级,接下来我们才更好地过五关斩六将!好啦,我们下期再见。拜拜!