redux

redux

redux 基本介绍

redux 是一个状态机。这个是用来管理状态的。

这里要澄清一点, redux 并非 Facebook 推出的,而是由一个个人作者 Dan Abramov 所推出。

redux 和 react 的关系

两者之间本来没有任何关系,我们可以将 redux 用于 react、vue、angular 等技术,都可以用 redux,只不过 redux 和 react 配合得最好,一起出现的频率最多,所以之后在开发 react 应用的时候,自然而然就会想到使用 redux 来管理 react 应用的状态。

这因为这个原因,所以之后官方推出了 react-redux。

redux 的哲学

redux 中所涉及到的哲学有 3 个。

  1. single source of truth

翻译成中文叫做“单一真相”。所谓单一真相,使用一个 store 仓库来进行所有组件的状态管理。

  1. state is read-only

翻译成中文就是“状态只读”。store 里面的状态,我们只能读取,不可以(直接)修改。

在 redux 中,虽然不能直接修改仓库的状态,但是可以生成一份新的状态树,用新的状态树去覆盖旧的状态树。

  1. changes are made with pure function called reducer

如果要改变仓库的数据,需要使用纯函数来修改,这个纯函数在 redux 中被称之为 reducer。换而言之,就是使用 reducer 来修改仓库的数据。

接下来,简单介绍一下什么是纯函数。

纯函数是来自于函数式编程的概念。

编程范式:

  • 命令式编程:告诉计算机怎么做(How)
  • 声明式编程:告诉计算机我想要什么(What)

这两种编程范式中,一直是命令式发展的比较迅速。相比声明式,命令式编程要简单很多,简单易学。

命令式编程:

- 面向过程
- 面向对象

声明式编程:

- DSL(领域专用语言:CSS、SQL)
- 函数式编程(指的是数学里面的函数,没有变量)

纯函数:所谓纯函数,是指对于指定输入,返回指定输出,不存在副作用。

function test(x){
  return x + 1;
}
redux 的入门示例

首先,在正式介绍redux 之前,我们先书写一个 react 版本的计数器。

import React,{useState, useRef} from 'react'
function App() {

  let [count,setCount] = useState(0);
  let selRef = useRef();// 创建一个引用

  // 增加
  const increment = ()=>{
    // 1. 先获取下拉列表里面的值 2. count 增加
    let num = selRef.current.value * 1
    setCount(count + num);
  }

  // 减少
  const decrement = ()=>{
    // 1. 先获取下拉列表里面的值 2. count 增加
    let num = selRef.current.value * 1
    setCount(count - num);
  }

  // 奇数增加
  const incrementIfOdd = ()=>{
    if(count % 2 == 1){
      let num = selRef.current.value * 1
      setCount(count + num);
    }
   
  }

  // 异步增加
  const incrementAsync = ()=>{
    setTimeout(()=>{
      let num = selRef.current.value * 1
      setCount(count + num);
    },2000)
  }

  return (
    <div className="App">
      <p>你点击了 {count}</p>
      <select name="" id="" ref={selRef}>
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
      </select>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
      <button onClick={incrementIfOdd}>奇数增加</button>
      <button onClick={incrementAsync}>异步增加</button>
    </div>
  );
}

export default App;

观察上面的代码,我们发现,目前为止,没有只有 redux,组件内部自己维护了一组状态。

首先需要安装 redux:

npm i redux

接下来,在 src 下面新建 redux 目录,创建 4 个文件:

  • actions:描述状态如何进行修改,action 是一个对象。
  • actionType:action 的类型
  • reducers:纯函数,负责修改仓库的状态,之后 action 这个对象就会被派发到 reducer里面,从而生成新的状态树,去覆盖旧的状态树。
  • store:仓库,存储了所有组件的状态。

接下来书写 redux 版本,代码如下:

// actionType.js
// action 的类型
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'


// actions.js
// 描述状态如何修改,导出一系列的生成 action 对象的工厂函数
// action 是对象,对象用来描述如何对状态进行修改
// 导出两个方法,工厂函数,专门用于生成 action 对象的

import {INCREMENT,DECREMENT} from './actionType'
// action 里面书写了生成 action 对象的工厂函数
// 回头根据传入的 num 会返回一个 action 对象
// action 对象是对状态如何进行修改的一个描述
// 之后这个 action 会被派发到 reducer 里面
export const increment = (num)=>({
    type : INCREMENT,
    data : num
})

export const decrement = (num)=>({
    type : DECREMENT,
    data : num
})

// reducer.js
// reducer 是一个纯函数,接收两个参数,第一个是初始状态,第二个是 action 对象
import { INCREMENT,DECREMENT } from "./actionType";

// 这里我们导出了一个名为 counter 的函数,这个就是一个纯函数,也是 redux 里面称之为的 reducer
// 函数接收两个值,初始状态,action 对象
export default function counter(state=0, action){
    switch(action.type){
        case INCREMENT:
            return state + action.data
        case DECREMENT:
            return state - action.data
        default: return state;
    }
}

// store.js
// 仓库文件,调用 redux 里面有一个 createStore 的方法,接收一个 reducer 作为参数
// 这就是我们的仓库
import {createStore} from 'redux'
import counter from './reducers'

// 使用 createStore 方法创建仓库的时候
// 接收一个 reducer 作为参数
export default createStore(counter);

// index.js
// 将仓库挂载到根组件上面,监听 store 状态的变化,只要一变化,我们就要重新渲染
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import store from "./redux/store.js"; // 引入仓库
// 接下来需要将这个仓库挂在根组件上面

const render = ()=>{
  ReactDOM.render(
    <React.StrictMode>
      <App store={store}/>
    </React.StrictMode>,
    document.getElementById('root')
  );
}
render();

// 之后,只要仓库的状态发生变化,那么我们就应该重新渲染视图
store.subscribe(render);

// App.jsx
// 不再拥有自己的状态,状态从 store 里面获取。store.getState() 来获取状态
// 修改仓库状态:派发一个 action 到 reducer
props.store.dispatch(increment(num));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值