首页IT科技redux入门教程阮一峰(Redux的基本使用过程详解)

redux入门教程阮一峰(Redux的基本使用过程详解)

时间2025-05-03 06:59:07分类IT科技浏览3167
导读:Redux的使用过程 Redux测试项目的搭建...

Redux的使用过程

Redux测试项目的搭建

1.创建一个新的项目文件夹:learn-redux

# 执行初始化操作 npm init -y或yarn init -y

# 安装redux:npm install redux --save或yarn add redux

2.创建src目录           ,在src目录下创建一个store文件夹, 并且在该文件夹下创建index.js文件

3.可以修改package.json用于执行index.js, 也可以不配置, 直接使用node命令运行

"scripts": { "start": "node src/index.js" }

Redux的基本使用步骤

1.创建一个对象                ,作为我们要保存的状态state:

// 由于测试项目在node环境下, 因此使用require方式导入 const { createStore } = require("redux") // 创建的要存储的state: initialState const initialState = { name: "chenyq", age: 18 }

2.创建Store来存储这个state

由于创建的state是不能直接放到创建的store中的, 需要通过reducer将数据添加到store中, 因此创建store时必须创建reducer;

reducer函数的返回值, 会作为store之后存储的state

// 定义reducer, 将要存储的state作为返回值返回 function reducer() { return initialState } // 创建的store, 内部会自动回调reducer, 拿到initialState const store = createStore(reducer) // 导出store module.exports = store

我们可以在其他文件中通过 store.getState 来获取当前的state;

// 导入创建的store const store = require("./store") // 获取store中的state console.log(store.getState())

3.通过action来修改state

错误演示: 直接修改store

store.getState().name = "abc"

修改store中的数据不能直接修改, 必须要通过dispatch来派发action;

通常action中都会有type属性      ,也可以携带其他的数据;

// 定义一个action const nameAction = { type: "change_name", name: "abc" } // 派发action store.dispatch(nameAction)

当然上面代码中, 也可以写为一行

// 派发action store.dispatch({ type: "change_name", name: "abc" })

4.修改reducer中的处理代码

reducer接收两个参数:

参数一: store中当前保存的state

参数二: 本次需要更新的action

只要调用dispatch就会重新执行reducer函数

这里一定要记住           ,reducer是一个纯函数                ,不可以直接修改state, 后面我会讲到直接修改state带来的问题;

// 第一次state是undefined, 因此给一个默认值将初始化数据添加到store中 function reducer(state = initialState, action) { // 有数据更新时, 返回一个新的state if (action.type === "change_name") { return { ...state, name: action.name } } // 没有数据更新时, 返回之前的state return state }

5.可以在派发action之前      ,监听store的变化:

通过store.subscribe()函数可以监听store中的数据变化

store.subscribe()函数的参数接收一个函数, 该函数在store数据发生更新自动回调

const store = require("./store") // 例如: 监听数据的变化, 当store变化, 就获取最新的state store.subscribe(() => { console.log(store.getState()) }) store.dispatch({ type: "change_name", name: "abc" }) store.dispatch({ type: "change_name", name: "aaa" })

6.封装函数动态生成action

例如上面代码中, 我们修改名称多次, 只有传入的action的name属性值不相同, 那么我们可以封装一个函数, 动态的生成action, 这也是开发中一贯的做法

// 创建修改name的action const changeNameAction = (name) => ({ type: "change_name", name }) // 创建修改age的action const changeAgeAction = (num) => ({ type: "change_age", num }) // 在派发action时, 我们就可以调用函数即可获取action store.dispatch(changeNameAction("aaa")) store.dispatch(changeNameAction("bbb")) store.dispatch(changeNameAction("ccc")) store.dispatch(changeAgeAction(10)) store.dispatch(changeAgeAction(20)) store.dispatch(changeAgeAction(30)) store.dispatch(changeAgeAction(40))

Redux目录的结构划分

如果我们将所有的逻辑代码写到一起     ,那么当redux变得复杂时代码就难以维护           。

例如上面代码中, 我们封装的动态创建action的函数, 这种动态生成action的函数在项目中可能会有很多个, 而且在其他多个文件中也可能会使用, 所以我们最好是有一个单独的文件夹存放这些动态获取action的函数

接下来                ,我会对代码进行拆分           ,将store           、reducer                、action      、constants拆分成一个个文件                 。

创建store/index.js文件: index文件中, 我们只需要创建store即可

const { createStore } = require("redux") // 引入reducer const reducer = require("./reducer") // 创建的store, 内部会自动回调reducer, 拿到initialState const store = createStore(reducer) // 导出store module.exports = store

创建store/reducer.js文件: 在真实项目中, reducer这个函数我们会越写越复杂, 造成我们index.js文件越来越大, 所以我们将reducer也抽离到一个单独的文件中

const { CHANGE_NAME, CHANGE_AGE } = require("./constants") // 创建的要存储的初始化state const initialState = { name: "chenyq", age: 18 } // 定义reducer, 将要存储的state作为返回值返回 // 第一次state是undefined, 因此给一个默认值将初始化数据添加到store中 function reducer(state = initialState, action) { switch(action.type) { case CHANGE_NAME: return { ...state, name: action.name } case CHANGE_AGE: return {...state, age: state.age + action.num} } // 没有数据更新时, 返回之前的state return state } module.exports = reducer

创建store/constants.js文件: 将type的类型定义为常量(防止写错的情况), 这些常量最好也防止一个单独的文件中

// store/constants.js const CHANGE_NAME = "change_name" const CHANGE_AGE = "change_age" module.exports = { CHANGE_NAME, CHANGE_AGE }

创建store/actionCreators.js文件: 将封装的动态创建action的函数放在该文件中, 在需要使用的地方导入即可

const { CHANGE_NAME, CHANGE_AGE } = require("./store/constants") // 创建修改name的action const changeNameAction = (name) => ({ type: CHANGE_NAME, name }) // 创建修改age的action const changeAgeAction = (num) => ({ type: CHANGE_AGE, num }) module.exports = { changeNameAction, changeAgeAction }

最终形成如下目录结构, 这也是官方推荐的目录结构, 一个store中包含这四个文件夹

注意:node中对ES6模块化的支持, 建议使用CommonJS规范

React的三大原则

单一数据源

整个应用程序的state被存储在一颗object tree中     ,并且这个object tree只存储在一个 store 中:

Redux并没有强制让我们不能创建多个Store                ,但是那样做并不利于数据的维护;

单一的数据源可以让整个应用程序的state变得方便维护           、追踪                、修改;

State是只读的

唯一修改State的方法一定是触发action           ,不要试图在其他地方通过任何的方式来修改State:

这样就确保了View或网络请求都不能直接修改state,它们只能通过action来描述自己想要如何修改state;

这样可以保证所有的修改都被集中化处理                ,并且按照严格的顺序来执行                ,所以不需要担心race condition(竟态)的问题;

使用纯函数来执行修改

通过reducer将旧state和actions联系在一起,并且返回一个新的State:

随着应用程序的复杂度增加           ,我们可以将reducer拆分成多个小的reducers                ,分别操作不同state tree的一部分;

但是所有的reducer都应该是纯函数      ,不能产生任何的副作用;

声明:本站所有文章           ,如无特殊说明或标注                ,均为本站原创发布     。任何个人或组织      ,在未征得本站同意时     ,禁止复制      、盗用     、采集                、发布本站内容到任何网站           、书籍等各类媒体平台     。如若本站内容侵犯了原著者的合法权益                ,可联系我们进行处理                 。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
seo排名优化什么意思(seo排名优化方法) 搜索引擎排名优化的实践方法(打造网站流量和转化利器)