内容简介:我不萌,但新。2018年要结束了,这一年,我。。。算了,不多说了。想起上半年看的 react,到现在也没怎么用过,都快忘光了,趁现在有时间我来捋捋,首先从 redux 下手(与 react 有啥什么关系???:joy:)
我不萌,但新。
2018年要结束了,这一年,我。。。算了,不多说了。
想起上半年看的 react,到现在也没怎么用过,都快忘光了,趁现在有时间我来捋捋,首先从 redux 下手(与 react 有啥什么关系???:joy:)
为什么用 redux
我想学习 redux 的同学多少知道它的作用,官方定义 redux 是一个面向 JavaScript 应用的可预测状态容器。如果用过 vuex 的,就能明白它是干嘛的,它们作用是一样的,主要用来管理共享状态。不同于 vuex 与 vue 的关系,redux 与 react 是解耦的,虽然 redux 通常用在 react 中。至于为啥要用 redux,我觉得一张图更好说明问题:
在react应用中,父子组件之间的数据传递比较容易,但是在复杂组件层级关系中,如图左所示的那样,数据的传递就显得很麻烦了,而且容易混乱,这时如果有一个容器帮我们统一管理数据,并能共享到每个组件,那就很方便我们开发了,如图右所示。而redux正是一个提供这样功能的数据框架。
基本概念
概念这东西我不好说,我还是拿一张图说明:
在 react 中使用 redux 时,某组件需要一个数据,那么它就需要触发一个 action,通过 dispatch 给 store,表明自己需要数据啦,action 是行为动作,它告诉 store 需要什么样的数据,它也是 store 数据的唯一来源。store 相当于一个管理员,它自己不直接处理数据,而是把当前的数据和收到的 action 告诉 reducer,让 reducer 来处理数据,并将新数据返还给 store,再由 store 传递给组件,组件拿到的就是目标数据了。
初看时,可能有点绕,我们可以理解为一个在图书馆借书的场景。组件( Component)就相当于借书人,他要告诉管理员(Store),说:"我要借《时间简史》",那么说的这句话就可以理解为 Action,管理员(Store)听到后,他不可能记得每本书的位置,于是就查看记录本看看书的信息,那么这个记录本就相当于 Reducer,找到书的信息后,管理员(Store)就把信息告诉了借书人(Component)。可能比喻并不是那么恰当,但表达的意思也差不多了。redux 就是围绕 Action,Store,Reducer 这三点来展开的。
基本使用
为了方便起见,我直接用 create-react-app 脚手架创建一个项目来演示代码,安装以及创建我就略过了。把项目中多余的文件删除,src 目录下只保留一个 index.js 文件。
之前说过,redux 和 react 是解耦的,那么我们先只在 index.js 文件中来使用一下 redux,使用前别忘记安装以下 redux
npm install redux 复制代码
index.js
// 引入 createStore 方法,用于创建 store import { createStore } from "redux" // 默认初始状态 const defaultState = { a: 1 } // 创建 reducer function reducer(state = defaultState, action) { switch (action.type) { case "ADD": return Object.assign({}, state, { b: action.num }); default: return state; } } // 创建 store const store = createStore(reducer) // 获取 state console.log('dispatch action 之前的数据:',store.getState()) // 派发 action store.dispatch({ type:"ADD", num:2 }) // 获取更新后的 state console.log('dispatch action 之后的数据:',store.getState()) 复制代码
运行结果如图:
以上就是一个redux的最基本的使用过程,我们来看下。
reducer
首先说一下 reducer,它用来处理数据,本质上是一个函数,有两个参数 state 和 action,state 即是保存的状态,如果不给他赋初始值,那么它就等于 undefined
,我在这里给了它一个初始值 defaultState。action 即是行为,它是一个对象,必须有一个名为 type 的字段来表示将要执行的动作,如代码里的 ADD
就是我传入的一个表示添加的行为,(注意type的值可任意,应尽量语意化)。除了 type 字段外,你可以任意添加自己需要的字段,比如这里我传里一个 num 字段,我需要将它添加到 state 中去。
reducer的注意事项:
- 不要直接修改 state。可以看到,我再代码里使用 Object.assign() 新建了一个副本,再返回的。若不创建副本,redux 的所有操作都将指向内存中的同一个 state,所有的 state 都将被最后一次操作的结果所取代,我们将无法追溯 state 变更的历史记录。
- 在 default 情况下返回旧的 state。即没有 action 时,一定要返回旧的 state。
action
前面说了 action 本质上是一个JavaScript中的对象,约定 action 内必须使用一个字符串类型的 type 字段来表示将要执行的动作。多数情况下,type 会被定义成字符串常量。当应用规模越来越大时,建议使用单独的模块或文件来存放 action,如下:
// actionTypes.js export const ADD = "ADD" 复制代码
import { ADD } from './actionTypes' const action = { type: ADD, num: 2 } 复制代码
通过 store.dispatch()
方法将 action 传到 store。
store
store将 action 和 reducer 联系起来,维持应用的 state,可以通过 store.getState()
来获取 state,通过 store.dispatch()
来更新 state。我们通过引入 createStore 方法,并传入 reducer 为第一个参数来创建 store。
在 react 中使用 redux
前面介绍了 redux 的基本使用方法,但是我们最终还是要使用在 react 中,现在我们就结合 react 来用下 redux。
首先,修改项目目录,添加 store
目录,用来存放 redux 相关文件,而 src/index.js
文件为组件入口:
我们就写一个烂大街的计数器的例子,通过加减按钮实现数字的增减。
首先是store中的代码:
actionTypes.js 用来统一存放 action 的 type 类型,并导出
// 增 export const ADD = "ADD"; // 减 export const REDUCE = "REDUCE"; 复制代码
reducer.js 创建 reducer 函数,并导出
import { ADD, REDUCE } from "./actionTypes"; const defaultVal = 0; function reducer(state = defaultVal, action) { switch (action.type) { case ADD: let newVal1 = state + 1; return newVal1; case REDUCE: let newVal2 = state - 1; return newVal2; default: return state; } } export default reducer; 复制代码
index.js 文件创建 store,并导出
import { createStore } from "redux"; import reducer from "./reducer"; const store = createStore(reducer); export default store; 复制代码
然后 src/index.js 文件,是组件入口:
import React, { Component } from "react"; import ReactDOM from "react-dom"; import { ADD, REDUCE } from "./store/actionTypes"; import store from "./store"; class APP extends Component { render() { return ( <div> <div>{store.getState()}</div> <div> <button onClick={this.handleReduce.bind(this)}>-</button> <button onClick={this.handleAdd.bind(this)}>+</button> </div> </div> ); } // 执行减操作 handleReduce() { store.dispatch({ type: REDUCE }); } // 执行加操作 handleAdd() { store.dispatch({ type: ADD }); } } ReactDOM.render(<APP />, document.getElementById("root")); 复制代码
此时运行项目,在浏览器中实现加减操作。但是会发现并没有用,怎么点击都没有预想的效果。其实这里少了关键的一步,在 react 中使用不同于第一个例子里那样,第一个例子中我 dispatch 后会重新获取 state,也就是 store.getState()
,但在 react 组件里使用时,可以看到我只是获取了一次 state,那么我想要的效果是每当我 dispatch 后,这个 state 会自动更新。
redux 中提供了这样的一个功能,就是 store.subscribe(listener)
,它是 store 下的一个方法,会添加一个变化监听器,每当 dispatch action 的时候就会执行。那么有了监听器,每次 dispatch 时我们需要执行啥呢?没错,我们给组件重新 render 下。修改 ReactDOM.render
这部分代码,如下:
function render() { ReactDOM.render(<APP />, document.getElementById("root")); } render(); store.subscribe(render); 复制代码
用一个函数包裹 ReactDOM.render
方法,并执行,这个函数其实就是 listener 了,把它传给 subscribe,这样每次 dispatch 后,就可以更新 state 了。
以上就是结合 react 和 redux 的一个简单入门小例子,我写的不一定清楚,但是代码敲一遍也能了解个大概。
文中有写的不对的地方,望有大佬指点。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- TiDB入门(四):从入门到“跑路”
- MyBatis从入门到精通(一):MyBatis入门
- MyBatis从入门到精通(一):MyBatis入门
- Docker入门(一)用hello world入门docker
- 赵童鞋带你入门PHP(六) ThinkPHP框架入门
- 初学者入门 Golang 的学习型项目,go入门项目
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。