Redux基础篇

Redux基本概念

按照官方文档的说法:

Redux 是 JavaScript 状态容器,提供可预测化的状态管理。

然而并不是说做react的项目就一定需要使用redux,如果项目的组件通信简单,那么完全没有没有必要使用
但是用户的使用方式复杂,而且某个组件的状态需要共享、某个状态需要在任何地方都可以拿到、一个组件需要改变全局状态、一个组件需要改变另一个组件状态。这些情况下使用Redux将会变得简单,管理代码也不会那么复杂。

下面这张图贯穿了整个Store的思路:

Redux基础篇

通过上面的图我们知道Redux的核心由三部分组成:Store, Action, Reducer。

  • Store : 整个项目的数据都应该存储在这里。
  • Action:是个对象,必须包含type这个属性,reducer将根据这个属性值来对store进行相应的处理。除此之外的属性,就是进行这个操作需要的数据。
  • Reducer: 是个函数。接收两个参数:要修改的数据(state) 和 action对象。根据action.type来决定采用哪种操作,对state进行修改,最后返回新的state。

1.store

首先我们通过redux提供的createStore这个方法来创建一个Store

//index.js
import { createStore } from 'redux'
const store = createStore()
export default store

createStore的作用就是为了生成一个store对象。

store我们已经创建好了,打个比方:此时的store相当于图书馆的管理员,但是这个管理员记不住到底要怎么管理这些书籍,她需要一个小笔记本来帮助她来管理这些数据。所以,在创建这个管理员(store)的同时也要把这个小笔记本(reducer)给到这个管理员(store),要不然她都不知道怎么管理这些书籍(数据)

接下来怎么创建笔记本(reducer)呢?

2.reducer

首先我们要创建一个名叫reducer.js的文件。

reducer相当于记录了图书馆的所有书籍(数据),以及如何处理书籍(数据),所以这个笔记本要记很多内容

//reducer.js
const defaultState = {
    inputValue: '',
    list: ["javaScript", 'react', 'vue', 'jquery']
}

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

这里的defaultState就是存储图书馆的所有书籍(数据),然后将defaultState赋值给state后将新的state的值return出去

这样我们就创建了个笔记本啦!下面就是如何将管理员(store)和笔记本(reducer)连接起来

在index.js文件中我们用函数createStore已经创建了store,这个函数可接收一个参数,我们可以利用这个函数将reducer当做参数传给store,这个时候就可以把他们连接起来了。
首先我们需要在index.js引入reducer文件

import { createStore } from 'redux'
import reducer from './reducer'
const store = createStore(reducer)
export default store

代码写到这,管理员(store)就知道这个图书馆有多少书(数据),也可以到笔记本(reducer)里查看了

接下来我们就可以在组件里面使用store了

3.组件里使用store的数据

将创建store的文件index.js文件引入组件中,利用store.getState()来获取store里面的数据

constructor(props){
        super(props)
        this.state = {...store.getState()}
    }

这样就可以简单的从store里面获取数据显示在页面上了

但是,有时候我们的需求往往没有这么简单,现在我有个input框的值是从store里获取的,需要通过改变store然后再显示到页面上,那么我们要怎么告诉store 要改变数据呢?

4.action

首先我们需要监听input框的变化的函数handleChange。

handleChange(e) {
        const action = {
            type: "change_input_value",
            value: e.target.value
        }
        store.dispatch(action)
    }

action从表面理解就是一个动作。这个action是以一个对象的形式,里面有个type(意思是告诉store这个action是要做什么样的事情),除了 type 属性外,action 对象的结构完全由你自己决定。在这里我们添加一个value(input框要改变的)值

这时候这个action已经创建了,就需要调用store里面的一个方法dispatch来把action发送给store

这个时候action已经传给了store,但是store接收了action但是不知道该怎么处理这个数据,这时候他需要查这个笔记本(reducer),并且他要拿当前store里面的数据和接收到的action去查找这个笔记本(reducer),所以这个时候store要做个事情,就是要拿当前store里面的数据和接收到的action转发给reducer(很好的事情就是,store转发的这步是自动的,当store接收到action会自动将数据转发给reducer)
接下来我们可以验证一下:

//reducer.js
const defaultState = {
    inputValue: '',
    list: ["javaScript", 'react', 'vue', 'jquery']
}

export default (state = defaultState, action) =>{
    console.log("原来的state:" + state + ",接收到的action:" + action)
    return state
}

这样我们就可以从控制台看到每次改变input框的值都会输出state和action

5.Reducer

当reducer拿到了action就会去找到对应action要做的事情,这个时候action里的type就起作用了

const  defaultState = {
    inputValue: '',
    list: ["javaScript", 'react', 'vue', 'jquery']
}

export default (state = defaultState, action) =>{
    if(action.type === 'change_input_value'){
        const newState = JSON.parse(JSON.stringify(state))
        newState.inputValue = action.value
        return newState
    }
    return state
}

在这里reducer有个限制:reducer可以接收state 但是绝对不可以改变state
所以要深复制state给newState,然后将action.value 赋值给newState.inputValue,对应的值改变之后返回一个新的newState给store,store接收到这个newState时候,会将旧的state替换掉

到这里你以为结束那就是错了,实际情况是store里面数据改变了,但是组件里的数据还没有改变!!!

5.subscribe

最后一步就是要我们在组件里订阅store:store.subscribe(),当store里面的数据发生变化时subscribe这个函数就会被触发,
subscribe函数可以接收一个参数,我们可以利用这个给subscribe加个函数handleStoreChange,在函数handleStoreChange里面执行this.setState(store.getState()),这个时候store每次改变都会和组件里state的数据保持一致了

constructor(props){
        super(props)
        this.state = {...store.getState()}
        this.handleStoreChange = this.handleStoreChange.bind(this)
        store.subscribe(this.handleStoreChange)
    }
    handleStoreChange() {
        this.setState(store.getState())
    }

6.总结

Store有三个方法:

  • getState:用来获取store里面存储的数据。
  • dispatch: store里的数据不能直接修改,只能通过触发action来进行修改,这个方法就是用来触发action。
  • subscibe:订阅store改变时,要进行的操作。比如在react中,当store改变时,我们需要调用render方法对视图进行更新。

思路:

  • 首先用createStore生成一个store,并且将创建好的reducer作为createStore参数传给store,这样store和reducer就可以连接起来了
  • 页面要使用的时候利用store.getState()来获取store里面的值
  • 当要改变store里面的值的时候,就需要创建一个action对象,并用store.dispatch(action)来传给store,store接收后会自动传给reducer,reducer做相应的处理将新的state传给store
  • 最后在组件里利用store.subscribe()订阅store

相关推荐