我自己的理解 redux 就跟 vue 中的 vuex 差不多, 都是数据管理器, 话不多说, 我们从经典的计数器案例开始讲解
使用 redux 实现计数器
创建如下的 react 项目, 我习惯把每一个模块分块, 才有这么多文件, 当然你也可以写在一个 js 文件中, 这不是重点
首先我们看一下项目的入口文件 index.js
- import 'core-js/fn/object/assign';
- import React from 'react';
- import ReactDOM from 'react-dom';
- import Counter from './components/Counter'; // 引入计数器件
- import {createStore} from 'redux'; // 通过解构赋值得到 createStore, 为 store 的创建做准备
- import reducer from './reducers/index' // 引入 reducer 纯函数 该函数, 根据 action 的 type 不同结合旧的 state 返回新的 state
- let store = createStore(reducer); // 创建 redux 的核心 store store 我会在后面进行详细的解答
- import {numAdd,numDel} from './actions/index'; // 引入 action 函数, 触发什么操作, 就根据操作怎样改变值
- // Render the main component into the dom
- // 这里使用 Redducer 变量来定义 ReactDOM 中的 render 函数, 是方便 store 中 state 更新之后, 页面的渲染
- const Redducer = () =>{
- ReactDOM.render(
- <Counter
- value={store.getState()}
- add ={()=>store.dispatch(numAdd())}
- del ={()=>store.dispatch(numDel())}
- ></Counter>,
- document.getElementById('app')
- );
- };
- // value={store.getState()} 给展示组件 Counter 传递数据 这里的 store.getState()得到的值, 就是 store 创建过程中 reducer 纯函数里面的初始 state 值
- // ()=>store.dispatch(numAdd())和()=>store.dispatch(numDel()) 定义函数传递给展示组件 Counter
- //store.dispatch(参数)会传递一个对象作为参数例如{type:"add"}, 调用 reducer 纯函数, 实现 store 中的 state 的更新
- Redducer();// 该函数执行, 就初始化了页面
- store.subscribe(Redducer);
- //store.subscribe()用来监听 store 中大的 state 是否发生改变, 如果发生改变, 就重新渲染页面, 所以才跟 Redducer()进行绑定
在看纯函数 reducer, 至于为什么 redux 负责 state 编辑的函数统称 reducer, 我自己的猜测是根据 es5 中的 reduce 方法有关(纯属瞎猜测, 切勿当真)
- const reducer = (state=0,action)=>{
- switch (action.type){
- case 'add':
- return state+1;
- case 'del':
- return state-1;
- default:
- return state
- }
- };
- // 定义 store 的 state = 0,action 接受的值就是 store.dispatch(numAdd())中通过 numAdd()函数的到的一个对象
- // 由于前面在得到 store 的时候 该函数跟 redux 中的 createStore 进行了绑定 也就是这一句代码 let store = createStore(reducer)
- // 所以通过这里就可以改变 store 的 state 值, 所以说现在可以的理解 reducer 为什么是一个纯函数了吧
- export default reducer;
在看 actions 中的导出函数
- export const numAdd = ()=>{
- return{
- type:"add"
- }
- };
- export const numDel = ()=>{
- return{
- type:"del"
- }
- }
- // 导出两个函数, 每一个函数返回一个包含 type 属性的对象(注意 ation 中 type 是必须的, 其他的属性可以自行添加), 可以通过解构赋值得到每一个
- // 的函数, 就像入口文件 index.js 中的这一句代码 import {numAdd,numDel} from './actions/index';
最后看展示组件 Counter
- import React from 'react';
- // 函数返回组件的话, 就是解构赋值获取数据
- // const Counter = ({ value, add, del })=>{
- // return(
- // <div>
- // <p style={{color:'red'}}>
- // 点击次数{value}
- // </p>
- // <button onClick={add}>加一</button>
- // <button onClick={del}>减一</button>
- // </div>
- // )
- // };
- //class 返回组件的话, 就是直接获取当前组件自身的属性, 就可以获取到自己想要的数据
- class Counter extends React.Component {
- render() {
- return (
- <div>
- <p style={{color: 'red'}}>
- 点击次数{this.props.value}
- </p>
- <button onClick={this.props.add}>加一</button>
- <button onClick={this.props.del}>减一</button>
- </div>
- )
- }
- }
- export default Counter;
在这里我使用了两种方式来创建组件, 第一种通过函数的方式创建的组件, 要获取在入口文件 index.js 中传过来的数据, 只能通过形参解构赋值的到数据, 第二种通过 class 创建的组件只能通过组件自身的属性, 来获取数据, 当然也可以通过解构赋值来得到自己想要的数据, 代码如下
- class Counter extends React.Component {
- render() {
- let {value,add,del} = this.props;
- return (
- <div>
- <p style={{color: 'red'}}>
- 点击次数{value}
- </p>
- <button onClick={add}>加一</button>
- <button onClick={del}>减一</button>
- </div>
- )
- }
综上所有的代码就可以实现了简单的计数器的功能, 这就是 redux 最基本的使用方法, 提示: redux 和 reat-redux 需要自己安装, 最好使用 --save 来安装
接下来就是使用 redux 和 react-redux 来实现计数器
且看代码
- import React, { Component } from 'react' // 引入 react
- import PropTypes from 'prop-types' // 引入限制 UI 组件 (展示组件) 属性限制
- import ReactDOM from 'react-dom' // 引入 react-dom 相关的对象
- import { createStore } from 'redux' // 引入 redux
- import { Provider, connect } from 'react-redux'// 引入 react 配套的 redux
- // 创建 react 组件(或者是虚拟节点)
- class Counter extends Component {
- render() {
- const { value, onIncreaseClick } = this.props;
- // 通过解构赋值得到相应的属性里面的值
- // 在这里 Counter 是 UI 组件 (展示组件) 其属性是其外面的容器组件中的 state 是通过 react-redux 中的 connect 操作之后传递过来的
- return (
- <div>
- <span>{value}</span>
- <button onClick={onIncreaseClick}>Increase</button>
- {/* 通过点击事件触发绑定的属性, 很明显, 在这里 onIncreaseClick 是一个方法或者是一个对象的 key 值, 其映射的 value 值是一个函数 */}
- </div>
- )
- }
- }
- // 对展示组件中属性各个值得类型进行限制 不合符规则会报错
- Counter.propTypes = {
- value: PropTypes.number.isRequired, // 属性对象中的 value 必须是 number 类型还有必须有值
- onIncreaseClick: PropTypes.func.isRequired // 属性对象中的 onIncreaseClick 必须是函数还有必须有值
- };
- // 这里定义的是一个 action 对象, 我的理解就是跟 vuex 中 actions 的作用差不多, 发送不同的动作名称, 通过配套其他函数的监听
- // 实现容器组件的状态 (state) 的改变, 只不过 vuex 中的 actions 是发送动作名, redux 是根据 actions 对象中的 type 的值不同, 进行不同的操作
- const increaseAction = { type: 'increase' };
- // 定义 reducer 纯函数, reducer 函数的作用就是, 根据传过来的 action 和旧 state 的状态值
- // 然后根据 action 的 type 的值进行不同的操作, 进行新的 state 的返回, 从而达到 UI 组件 (展示组件) 的重新渲染
- function counter(state = { count: 0 }, action) {
- const count = state.count;
- switch (action.type) {
- case 'increase':
- return { count: count + 1 };
- default:
- return state
- }
- }
- // 创建 store 对象, 可以说 store 是 redux 的核心, 因为根据 redux 的设计理念,
- // 对 state 的操作都是根据 store 中的各种方法实现的, 便于管理
- // 在这里规定使用 redux 中的 createStore 和 reducer 纯函数结合来得到我们想要的 store
- const store = createStore(counter);
- //mapStateToProps 是 connect 的第一个参数
- // 根据名称我们知道是把之前 reducer 纯函数中的 state(状态)和展示组件的 props(属性)进行映射
- function mapStateToProps(state) {
- return {
- value: state.count
- }
- }
- // mapDispatchToProps 是 connect 的第二个参数
- // 根据名称我们可以知道是把 reducer 纯函数中之前 store 中的 dispatch 方法和展示组件的 props(属性)进行映射
- function mapDispatchToProps(dispatch) {
- return {
- onIncreaseClick: () => dispatch(increaseAction)
- }
- }
- // 这里定义 App 为 react-redux 设计理念中的容器组件
- // 通过 connect 中传递参数和展示组件 Counter 相结合得出相应的容器组件 App
- // 这里的容器组件 App 里面包含了展示组件 Counter
- const App = connect(
- mapStateToProps,
- mapDispatchToProps
- )(Counter);
- // 向目标元素渲染容器组件 App
- // 这里的组件 Provider 是一个 react-redux 中特殊的组件
- // 注意: 1. Provider 中有且只有一个子组件(这里就是 App 容器组件, 不一定是容器组件, 根据自己的业务需求自己操作)
- // 2. 使用 Provider 组件的好处是, 只需要给 Provider 组件设置属性, 那么其子组件和其子组件中的子组件都可以直接使用其对应的属性
- // 3. 避免了组件嵌套之后一个一个传递的复杂操作
- ReactDOM.render(
- <Provider store={store}>
- <App />
- </Provider>,
- document.getElementById('app')
- )
在这里就完成了 redux 和 react-redux 的结合使用, 通过自己的学习, 我发现了编程思想是多么的重要, 我感叹于 react-redux 这种思想的深度, 整体感觉干净, 使得展示组件和容组件既相互分离又有一定的结合, 兼职就是藕断丝连, 但是又不会违背组件分离的思想, 简直就是强大
, 好了基础的 redux 和 react-redux 的讲解就到此结束了, 后面我还会写出 redux 异步编程的理解, 毕竟现在的都是同步实现
来源: https://www.cnblogs.com/jsydb/p/9480216.html