Redux基本介绍

redux 是什么

Redux 是 javascript 应用的状态容器,提供可预测的状态管理。

当遇到如下问题时,建议开始使用 Redux:

你有很多数据随时间而变化

你希望状态有一个唯一确定的来源

你发现将所有状态放在顶层组件中管理已不可维护

redux 和 react 的关系

Redux并不只为react应用提供状态管理, 它还支持其它的框架。

为什么Rect要用 Redux

react 是 DOM 的一个抽象层(UI 库),并不是 Web 应用的完整解决方案。因此react在涉及到数据的处理以及组件之间的通信时会比较复杂。

对于大型的复杂应用来说,这两方面恰恰是最关键的。因此,只用 react,写大型应用比较吃力。

  1. 2014 年 Facebook 提出了 Flux 架构的概念,引发了很多的实现。
  2. 2015 年,Redux 出现,将 Flux 与函数式编程(reducer)结合一起,很短时间内就成为了最热门的前端架构。
  3. Flux 是最早的状态管理 工具,它提供了状态管理的思想,也提供对应的实现
  4. 除了 Flux、Redux 之外,还有:Mobx 等状态管理工具

在这里插入图片描述

主要的区别:组件之间的通讯问题

不使用 Redux (图左边) :

  • 只能使用父子组件通讯、状态提升等 react 自带机制
  • 处理远房亲戚(非父子)关系的组件通讯时乏力
  • 组件之间的数据流混乱,出现 Bug 时难定位

使用 Redux (图右边):

  • 集中式存储和管理应用的状态
  • 处理组件通讯问题时,无视组件之间的层级关系
  • 简化大型复杂应用中组件之间的通讯问题

数据流清晰,易于定位 Bug

react 多组件共享 - 案例

问题描述

多组件(跨层级的)共享数据
在这里插入图片描述

目录结构

├── src
   ├── store          # redux目录,一般约定叫store
   │   ├── index.js   # 定义并导出store. 其中会导入reducer
   │   └── reducer    # reducer函数
   ├── App.js         # 根组件,引入Father 和 Uncle组件
   ├── Father.js      # Father组件。其中引入了Son组件
   ├── index.js       # 项目的入口文件,会导入并渲染App.js
   ├── Son.js         # Son组件
   └── Uncle.js       # Unclde组件

使用redux来解决的思路

在这里插入图片描述

  1. redux可以无视组件层级
  2. 对于组件系统来说,redux就是一个第三方的,全局的变量

Redux 三个核心概念

图示
在这里插入图片描述

理解三个核心概念

核心概念:store、action、reducer

action

动作。

一个js对象,包含两个属性:

  • type: 标识属性,值是字符串。多个type用action分开
  • payload:数据属性,可选。表示本次动作携带的数据

actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新 state。

特点:

  • 只描述做什么
  • JS 对象,必须带有 type 属性,用于区分动作的类型
  • 根据功能的不同,可以携带额外的数据,配合该数据来完成相应功能
{ type'increment' } 
{ type'decrement', count: 2 } 
{ type: 'addTodo', name: '吃饭' }
{ type: 'removeTodo', id: 3 }
 
{ type: 'addN', payload: n }
{ type: 'addN', payload: {count:2} }
{ type: 'addN', payload: {name:'吃饭',age:18} }
reducer

一个函数

作用

初始化状态

修改状态

修改状态

根据传入的旧状态和action,返回新状态

公式:(previousState, action) => newState

示例

const reducer = (state = 0, action) => {
  switch (action.type) {
    case 'add':
      // 返回新的state
      return state + 1
    case 'addN':
      // 返回新的state
      return state + action.payload
    default:
      return state
  }
}
store

store:仓库,Redux 的核心,整合 action 和 reducer

特点:

  1. 一个应用只有一个 store
  2. 维护应用的状态,获取状态:store.getState()
  3. 创建 store 时接收 reducer 作为参数:const store = createStore(reducer)
  4. 发起状态更新时,需要分发 action:store.dispatch(action)

其他 API, — 订阅(监听)状态变化:const unSubscribe = store.subscribe(() => {}) — 取消订阅状态变化: unSubscribe()

Redux功能演示核心代码

定义reuder

initState = 0
function reducer(state = initState, action) {
  return state
}

定义action

const action1 = { type:'addN', payload: 12 }
// store.dispatch(action1)
 
const action2 = { type:'add', payload: 1 }

定义store

import { createStore } from 'redux'
// 创建 store
const store = createStore(reducer)

store 相关API

  1. store获取状态 store.getState()
  2. store修改数据,通过派发action。store.dispatch({type:xxx, payload: xx}})
  3. store添加订阅者。
//  格式:
//  取消订阅 = store.subscribe(订阅者)
 
//  订阅者:就是一个函数,当state值变化时,store会执行它
//  store.subscript()的返回值也是一个函数,执行它时,它的
const unSubscribe = store.subscribe(() => {
  // 状态改变时,执行相应操作
})
 
// 取消监听状态变化
4. 取消订阅者。unSubscribe()

核心代码

import { createStore } from 'redux'
 
initState = 0
function reducer(state = initState, action) {
  return state
}
// 创建 store
const store = createStore(reducer)
 
// store获取状态
console.log(store.getState())
 
// 更新状态
//     1. dispatch 派遣,派出。表示:分发一个 action,也就是发起状态更新
//     2. store.dispatch会 调用reducer函数,并将action传递给reducer
const action1 = { type:'addN', payload: 12 }
store.dispatch(action1)
 
const action2 = { type:'add', payload: 1 }
store.dispatch(action2)
 
// store 添加订阅者
//  store.subscribe
//  订阅者:就是一个函数,当state值变化时,store会执行它
const unSubscribe = store.subscribe(() => {
  // 状态改变时,执行相应操作
  console.log('数据变化了....')
})
 
// 取消监听状态变化
unSubscribe()

Redux 代码执行过程

获取默认值

只要创建 store,那么,Redux 就会调用一次 reducer, 且type是一个随机值。如下是一个示例:
在这里插入图片描述

这一次调用 reducer 的目的:获取状态的默认值。这个初始值将成为下一次调用 store.getState() 方法来获取 Redux 状态值的preState

  • type是随机值确保了它不会被用户业务逻辑处理,而只能去匹配默认值。

更新状态

  • 当你需要更新状态时,就先分发动作 store.dispatch(action)
  • Redux 内部,store 就会调用 reducer,传入:上一次的状态(当前示例中就是:0)和 action({ type:
    ‘add’ }),计算出新的状态,并返回
  • reducer 执行完毕后,将最新的状态交给 store,store 用最新的状态替换旧状态,状态更新完毕
import { createStore } from 'redux'
const store = createStore(reducer)
 
function reducer(state = 0, action) {
  console.log('reducer:', state, action)
  switch (action.type) {
    case 'add':
      return state + 1
    default:
      return state
  }
}
 
console.log('状态值为:', store.getState()) // 10
 
// 发起更新状态:
// 参数: action 对象
store.dispatch({ type: 'increment' })
// 相当于: reducer(10, { type: 'increment' })
 
console.log('更新后:', store.getState()) // 11

解决问题-redux在react中使用

├── src
   ├── store          # redux目录,一般约定叫store
   │   ├── index.js   # 定义并导出store. 其中会导入reducer
   │   └── reducer    # reducer函数
   ├── App.js         # 根组件,引入Father 和 Uncle组件
   ├── Father.js      # Father组件。其中引入了Son组件
   ├── index.js       # 项目的入口文件,会导入并渲染App.js
   ├── Son.js         # Son组件
   └── Uncle.js       # Unclde组件

store/index.js

用reducer来初始化store

import { createStore } from 'redux'
import reducer from './reducer'
export default createStore(reducer)

reducer.js

设置初始值,并提供修改数据的逻辑

const initState = 0
export default function reducer (state = initState, action) {
  console.log(action)
  switch (action.type) {
    case 'addN':
      return state + action.payload
    case 'sub':
      return state - 1
    default:
      return state
  }
}

src/index.js

import react from 'react'
import reactDom from 'react-dom'
import App from './App'
 
import store from './store/index.js'
reactDom.render(<App />, document.getElementById('root'))
 
// 数据变化时,重新渲染
store.subscribe(() => {
  reactDom.render(<App />, document.getElementById('root'))
})

src/App.js

import react from 'react'
import Father from './Father'
import Uncle from './Uncle'
export default function App () {
  return (
    <div style={{ border: '1px solid #ccc', margin: 10, padding: 10 }}>
      根组件
      <Father />
      <Uncle />
    </div>
  )
}

son.js

获取数据: store.getState()

修改数据: store.dispatch(action)

import react, { useState } from 'react'
import store from './store/index'
export default function Son () {
  const [n, setN] = useState(12)
  const add = () => {
    store.dispatch({ type: 'addN', payload: n })
  }
  return (
    <div style={{ border: '1px solid #ccc', margin: 10, padding: 10 }}>
      子组件
      {store.getState()}
      <button onClick={add}>+n</button>
      <input value={n} onChange={(e) => setN(e.target.value)} />
    </div>
  )
}

uncle.js

修改数据: store.dispatch(action)

import react from 'react'
import store from './store/index'
export default function Uncle () {
  return (
    <div style={{ border: '1px solid #ccc', margin: 10, padding: 10 }}>
      Uncle组件
      <button
        onClick={() => {
          store.dispatch({ type: 'sub' })
        }}>
        -1
      </button>
    </div>
  )
}
  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值