redux基础篇

430 阅读6分钟

前景

在我们利用react编写项目的过程中,其实都知道,react其实只是一个视图层框架,为什么只是视图层框架呢,就从简单的组件传值说起,就像下面左边这棵树一样,每个节点都是一个组件,如果绿色组件想要传值给灰色组件,很多情况下都是会间接传值几次后才能到达目标。

在大型应用中,其实整个组件之间的传递是非常复杂而且难以维护的,所以仅仅使用react是不能管理好组件之间的传值的。 如果我们想要hold住一个大型应用,那么需要给react配套一个数据层框架——rudex,双剑合璧,共同使用!我们来看上面的图,当没有redux的时候,组件之间的传值其实是很复杂的,但是右图redux中要求我们把数据都存放到一个公共的存储区域————store中,这样一来组件想要获取其他组件的数据的时候,直接从store中取就好了。

这样看来,redux好像很不错,但是当业务代码很简单,数据源单一的时候,redux用起来就会感觉比较繁琐,添加的代码的复杂性,所以用不用redux其实就是看自己的代码是否需要使用,就像redux的作者说过这样的话:redux就像眼镜,你自会知道什么时候用它。

redux工作流程

上面我们说了,redux其实就是一个数据层框架,它将所有的数据都存放在了store中,那么redux的工作流程到底是怎样的呢?我们一起先来看看下面这幅图: 这幅图我们可以看出来其实就是一个图书馆的借书流程首先学生会说借书名称,管理员会通过电脑查询得知书本状态,最终将书本给到学生。

我为什么要先说明这样一个流程呢,其实就是个铺垫嘛,来,我们再来看下面这幅图:

其实上面图书馆的例子就是一个映射,我们就一一对应,通过图书馆结束流程来捋一捋redux工作流程:

当一个组件component需要获取store里的数据的时候,我们就会和store说:"我需要xxx数据呀",这句话就是通过ActionCreators创建的,当这句话创建好之后就会告知store,store并不知道组件需要什么样的数据,就需要去reducer查询一下数据,reducer就会告知store需要给什么数据,于是,store就兴高采烈的将这个数据返回给组件。

这就是redux的工作流程,虽然工作流程是明白了,但是我们该如何搭建,actionCreators、reducer这些到底是什么东西我们其实还没有特别理解。所以接下来let me code来告诉你这些到底是什么!

前提

讲store创建之前我需要一个搭档——TodoList,由它和我一起来告知你如何创建(todolist其实完全没必要使用redux,这只是为了告知如何使用,但是并不提倡在简单业务中使用)。

import React from 'react'
import { Button, Input, List } from 'antd'

class Todolist extends React.Component {
  //目前任何增删改的功能都没有实现
  handleChange = (e) => {
  
  }

  handleClick = () => {
  
  }

  handleDeleteClick = (index) => {
  
  }

  render() {
    return (
      <div style={{ margin: 20 }}>
        <Input
          style={{ width: 300, marginRight: 10 }}
          placeholder='Todo'
          value={1}
          onChange={this.handleChange}
        />
        <Button
          onClick={this.handleClick}
        >提交</Button>
        <List
        style={{ width: 300, marginTop: 10 }}
        bordered
        dataSource={[]}
        renderItem={(item, index) => (
          <List.Item onClick={() => this.handleDeleteClick(index)}>
            {item}
          </List.Item>
        )}
      /> 
        
      </div>
    )
  }
}

export default Todolist

安装redux

好了,现在我们在项目中安装redux:

npm i redux -D

创建store

store就是一个存储数据的仓库,redux提供createStore来创建store,但需要注意,整个store是唯一的,整个应用中只能存在一个store

import {createStore} from 'redux'

//接受一个函数,返回新的store
const store = createStore(fn)

export default store;

store提供三个方法:

  • getState() 获取当前state的状态
  • dispatch(action) 派发action传递给store,唯一传输通道
  • subscribe(listner) 监听数据的改变,可以实时改变页面上的内容

action

State 的变化,会导致 View 的变化。但是只能接触到 View。所以,State 的变化必须是 View 导致的。Action 就是 View 发出的通知,表示 State 应该要发生变化了。——阮一峰

action本质上是一个对象,它是将数据传递给store的唯一方法,它通常包含一个type属性,这个属性我认为相当于一个id,能够验证唯一性,还包含了需要传递给store的数据。

就拿TodoList中的Input的value变化来说就可以通过dispatch派发action给store来改变value的值:

actionCreator

当执行每个操作的时候,其实都要创建一个action,这样action会分散在组件的各个地方,很难维护,也很麻烦,所以我们可以创建一个actionCreator来对action进行管理:

创建reducer

前文说过store就相当于图书管理员,它记不住图书馆里的所有书本,所以我们需要通过电脑查询,这个电脑查询就是reducer,当action传递给store的时候,需要返回新的state,reducer就是state的计算过程。

reducer本身是一个函数,接受当前state和action作为参数,最终返回一个新的state。

//state相当于电脑中的所有书本数据,也就是各个组件数据
const defaultState = {

}
export default (state = defaultState, action) => {

  return state
}

所以在store中,createStore接受reducer这个函数,即可返回新的store

前文中Input的value发生变化就是通过reducer计算:

reducer函数有一个很重要的特征:纯函数,也就是说给定固定的输入就会由固定的输出,并且没有任何副作用,reducer只能够接收state,但是不能改变state,所以我们需要对它进行一层深拷贝。

其实上面的TodoList增删改我没有告诉怎么实现,但是其实和上面的例子都是一样的,感兴趣的童鞋可以自己尝试尝试

补充

redux三大基本原则

  • store是唯一的

    • 整个应用中只能存在一个store。
  • 只有store能够改变自己的内容

    • 很多人会误以为其实都是reducer在更新数据,其实不是的,reducer只是计算过程,它只是返回新的state给到store,由store来更新数据,就像宰相辅佐皇帝,最终的实施权力还在于皇帝,而不在于宰相。
  • reducer必须是一个纯函数

    • 给定固定输入会有固定输出
    • 不会存在副作用(对接收的参数不能进行修改)

注:此文为本人学习过程中的笔记记录,如果有错误或者不准确的地方请大佬多多指教,评论区欢迎指教呀~~