萌新 redux 入门

栏目: 服务器 · 发布时间: 5年前

内容简介:我不萌,但新。2018年要结束了,这一年,我。。。算了,不多说了。想起上半年看的 react,到现在也没怎么用过,都快忘光了,趁现在有时间我来捋捋,首先从 redux 下手(与 react 有啥什么关系???:joy:)

我不萌,但新。

2018年要结束了,这一年,我。。。算了,不多说了。

想起上半年看的 react,到现在也没怎么用过,都快忘光了,趁现在有时间我来捋捋,首先从 redux 下手(与 react 有啥什么关系???:joy:)

为什么用 redux

我想学习 redux 的同学多少知道它的作用,官方定义 redux 是一个面向 JavaScript 应用的可预测状态容器。如果用过 vuex 的,就能明白它是干嘛的,它们作用是一样的,主要用来管理共享状态。不同于 vuex 与 vue 的关系,redux 与 react 是解耦的,虽然 redux 通常用在 react 中。至于为啥要用 redux,我觉得一张图更好说明问题:

萌新 redux 入门

在react应用中,父子组件之间的数据传递比较容易,但是在复杂组件层级关系中,如图左所示的那样,数据的传递就显得很麻烦了,而且容易混乱,这时如果有一个容器帮我们统一管理数据,并能共享到每个组件,那就很方便我们开发了,如图右所示。而redux正是一个提供这样功能的数据框架。

基本概念

概念这东西我不好说,我还是拿一张图说明:

萌新 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 入门

以上就是一个redux的最基本的使用过程,我们来看下。

reducer

首先说一下 reducer,它用来处理数据,本质上是一个函数,有两个参数 state 和 action,state 即是保存的状态,如果不给他赋初始值,那么它就等于 undefined ,我在这里给了它一个初始值 defaultState。action 即是行为,它是一个对象,必须有一个名为 type 的字段来表示将要执行的动作,如代码里的 ADD 就是我传入的一个表示添加的行为,(注意type的值可任意,应尽量语意化)。除了 type 字段外,你可以任意添加自己需要的字段,比如这里我传里一个 num 字段,我需要将它添加到 state 中去。

reducer的注意事项:

  1. 不要直接修改 state。可以看到,我再代码里使用 Object.assign() 新建了一个副本,再返回的。若不创建副本,redux 的所有操作都将指向内存中的同一个 state,所有的 state 都将被最后一次操作的结果所取代,我们将无法追溯 state 变更的历史记录。
  2. 在 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 文件为组件入口:

萌新 redux 入门

我们就写一个烂大街的计数器的例子,通过加减按钮实现数字的增减。

首先是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 的一个简单入门小例子,我写的不一定清楚,但是代码敲一遍也能了解个大概。

文中有写的不对的地方,望有大佬指点。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

两周自制脚本语言

两周自制脚本语言

[日]千叶 滋 / 陈筱烟 / 人民邮电出版社 / 2014-6 / 59.00元

《两周自制脚本语言》是一本优秀的编译原理入门读物。全书穿插了大量轻松风趣的对话,读者可以随书中的人物一起从最简单的语言解释器开始,逐步添加新功能,最终完成一个支持函数、数组、对象等高级功能的语言编译器。本书与众不同的实现方式不仅大幅简化了语言处理器的复杂度,还有助于拓展读者的视野。 《两周自制脚本语言》适合对编译原理及语言处理器设计有兴趣的读者以及正在学习相关课程的大中专院校学生。同时,已经......一起来看看 《两周自制脚本语言》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

html转js在线工具
html转js在线工具

html转js在线工具