redux学习系列(一)

134 阅读4分钟

为什么需要redux

javaScript开发的应用程序,已经变得非常的复杂了,需要管理的状态越来越多,包括:服务器返回的数据,缓存数据,用户操作产生的数据等等, 这些状态可能被多个组件共享使用,一个状态的改变可能以前多个对象的联动变化,Redux就是一个帮助我们管理state的容器。 就是让不同组件间可以轻松的共享该数据,同时Redux通过强制单向数据流,使得应用程序的状态可预测和可控
简单的说:redux是js的状态(数据)管理器,让组件直接可轻松共享状态(数据)。

redux 设计理念

举个例子: 比如我有一个friends列表数据需要管理:

const initialState = {
    friends: [
        { name:"xiaoming", age:18 },
        { name:"xiaohong", age:22 },
        { name:"xiaozhang", age:44 }
    ]
}

页面A通过products.push的方式增加一条数据,页面B通过products[0].age = 20修改一条数据。这样没有统一的规范来操作这些数据,那整个数据的变化是无法追踪的。

Redux中是如何做的 ?

◆ store:
因为多个页面都需要用到friends数据,所以我们要将friends数据存入store

◆ action:
     变更数据,必须通过dispatch(派发) action 来更新
     action就是一个普通的js对象,描述了这次更新的 typeaction

下面就是几个action:

const action1 = { type: "ADD_FRIEND", info: {name:"lucy", age: 20}}
const action2 = { type: "INC_AGE", index: 0 }
const action3 = { type: CHANGE_NAME, playload: { index: 0, newName:"jay"}}

强制使用action的好处是: 数据变更都是根据action对象来做变化的,所以可清晰知道数据到底发生了什么变化,并且变化是可追踪,可预测的

◆ reducer:

我们已知Redux是通过派发action来做数据变更的,也就是说通过action中的type和content来修改state(数据),但action仅仅是个js对象(保存着要修改的数据),怎么让新数据修改掉旧state(数据)呢?
通过纯函数reducer来修改state(数据)。reducer会将传入的 state(旧)action 结合起立生成一个 新的state

下面就是一个reducer函数的写法:

function reducer(state = initialState, action) {
    switch (action.type){
        case "ADD_FRIEND":
            return {...state, friends:[...state.friends, action.info]}
        case "INC_AGE":
            return {xxxxxxxxx}
        default:
            return state;
    }
}

Redux简单使用:

这里先使用一个简单的,非React脚手架项目演示一下。

步骤:

首先,创建一个文件夹(LearnRedux), 在该文件夹下创建一个src文件夹,src文件夹下再创建一个store文件夹。

接着,执行 npm init -y 创建一个 package.json文件

image.png

◆ 安装redux库:

npm install reduxyarn add redux

image.png


◆ 在store目录下创建一个index.js:

image.png 第1行: 导入redux中的 createStore

第4行: 是要保存在store中的数据,真实开发中一般来自于网络请求

第15行: 定义一个reducer函数,用来将 action保存在store中的数据 产生联系(即:更改store中存储的数据)。 reducer是一个纯函数,这个函数在后面创建store的时候会被作为参数传入,传入后会被redux自动调用,并且会传递 state 和 action 给reducer函数。

第26行: 通过导入的 createStore函数创建一个store,入参就是定义的 reducer函数

第28行: 导出供其他使用


◆ 在某个页面中获取存储在store中的数据:

image.png

第1行: 导入我们创建的 store

第4行: 通过store的 getState() 方法获取存在在store中的共享数据


◆ 在某个页面中修改存储在store中的数据:

image.png 第1行: 导入我们创建的 store

第4行: 创建一个 action对象

第7行: 通过store的 dispatch() 方法派发action,对共享值进行修改。(派发的action对象会传递给reducer函数,reducer函数会被重新执行)


◆ 在某个页面中订阅存储在store中的数据:

当修改了store中的值,就会自动执行该回调函数

image.png

第1行: 导入我们创建的 store

第5行: 通过store的 subscribe() 函数, 对store中的数据进行订阅。函数入参是一个 回调函数 。这样一旦调用dispatch去修改store中的值,就会自动执行该回调函数

第15行:subscribe函数会返回一个新的函数,当调用这个新函数可以取消订阅,这样后面再对store中的值进行修改时,就不会执行第5行传入的那个 回调函数

通过控制台打印,我们可以发现修改成 "小李" 时,订阅回调函数没有执行,因为在修改成 小李 之前取消了订阅。
还发现第11行 和 12行 都是修改 name="小红", 订阅回调函数依旧会执行,也就是只要修改了store中的值,不管两次值是不是一样,都会调用订阅回调函数。


代码:gitee.com/wangsn001/r…