react

本人一直是用的vue进行开发,应公司内部需求,后续需要并行使用react框架进行开发,即开始从0学习react框架,以下就是我学习的心得,通过笔记的方式记录学习的内容。内容会根据每次学习的情况进行更改,直至学完为止。

一、创建react项目

注意:使用的是vscode编辑器
1、创建脚手架:(需要手动跟新,自己重新npm最新版本的脚手架)
例:npm install -g create-react-app
2、创建一个项目
1)全局安装:
ccreate-react-app one-app
2)不全局安装(临时安装,每次安装都是最新版的脚手架)
npx ccreate-react-app one-app
3、rcc快捷键出类组件基本框架,rfc函数组件基本框架(需要安装ES7插件)
例如输入rfc,出现函数组件基本框架结构
在这里插入图片描述

二、编写第一个react项目

在index.js文件中,将元素插入到根元素节点中。
在这里插入图片描述在这里插入图片描述

1、创建第一个类组件

在这里插入图片描述
在这里插入图片描述

2、创建第一个函数组件

在这里插入图片描述
总结

  • 组件命名必须是大写的。
  • render()函数是必需存在的且不能改名。
  • return后面若换行需要加上()。
  • return中只能有一个根元素。

三、组件嵌套

在这里插入图片描述
在这里插入图片描述

四、样式写法

在这里插入图片描述

  • {} 中可识别变量,表达式
  • class要写成className形式,部分属性会发生变更
  • 样式可写行内样式也可外部引入css文件

五、事件处理

前面添加on,即是事件处理函数
例如:
onClick 点击事件
onMouseOver 鼠标经过事件
在这里插入图片描述
总结:一共有四种事件绑定的写法,最推荐最后一种,能够传入参数,并且this指向不会出现问题。
特点:
1、react中并不会真正的绑定事件到每一个具体的元素身上,而是采用事件代理的模式;(通过冒泡到根节点上,占内存小)
2、和普通浏览器一样,事件handler会自动传入一个event对象
额外扩展知识点:( bind、call和apply方法的区别)
bind、call和apply都是JavaScript中用于改变函数执行上下文的方法,它们的区别如下:

  1. bind方法:bind方法会创建一个新的函数,并将原函数的执行上下文绑定到指定的对象。bind方法不会立即执行函数,而是返回一个绑定了执行上下文的新函数。这样可以在稍后调用该函数时,仍然保持原来的执行上下文。
  2. call方法:call方法会立即执行函数,并将指定的对象作为执行上下文。除了第一个参数是执行上下文外,call方法可以接受多个参数,这些参数会作为原函数的参数传递进去。
  3. apply方法:apply方法与call方法类似,也是立即执行函数并改变执行上下文。不同之处在于,apply方法接受一个数组作为参数,数组中的每个元素会作为原函数的参数传递进去。

总结一下:

  • bind方法返回一个新函数,并绑定了指定的执行上下文。
  • call方法立即执行函数,并将指定的执行上下文和参数传递进去。
  • apply方法立即执行函数,并将指定的执行上下文和参数数组传递进去。

六、组件的导入与导出(附加ES6知识)

一个js文件中只能有一个默认导出,但是可以有多个具名导出。
例如:
子组件中:

export function Profile() {//具名导出的方式
  return (
    <img
      src="https://i.imgur.com/QIrZWGIs.jpg"
      alt="Alan L. Hart"
    />
  );
}

export default function Gallery() {//默认导出的方式
  return (
    <section>
      <h1>了不起的科学家们</h1>
      <Profile />
    </section>
  );
}

父组件:

import Gallery from './Gallery.js'; //默认导入的方式
import { Profile } from './Gallery.js';//具名导入需以结构的方式

export default function App() {
  return (
    <Profile />
  );
}

总结:

语法导出语句导入语句
默认export default function Button() {}import Button from ‘./Button.js’;
具名export function Button() {}import { Button } from ‘./Button.js’;

七、ref

作用:给标签或者组件命名,拿到该标签或者组件,从而拿到值。
旧写法:(过时)
在这里插入图片描述
取值:ref=“name”
拿值:this.refs.name.value
新写法:
在这里插入图片描述
取值: myref = React.createRef(); ref={this.myref}
拿值:{this.myref.current.value

八、状态(state)(类组件)

状态就是组件描述莫种显示情况的数据,由组件自己设置和更改,也就是说由组件自己维护,使用状态的目的就是为了不同的状态下使组件的显示不同(自己管理)。
设置数据:
state={参数名:参数值},state固定写法
修改数据:
this.setState({参数名:参数值})
在这里插入图片描述
注意:

  • state可另外一种写法,写在构造函数中
    在这里插入图片描述 - setState可一次性更新多个状态在这里插入图片描述
    例子:渲染列表
    在这里插入图片描述
    使用jsx写法,可直接在js中嵌入html,{}内为变量。key属性必存在且值不唯一(diff算法,为了列表的复用和重排,设置key值,提高性能)。
    拓展:dangerouslySetInnerHTML属性将标签识当成html识别
    在这里插入图片描述
    在这里插入图片描述
    状态特点:

  • setState处在同步的逻辑中,异步跟新状态,异步跟新真实dom
    在这里插入图片描述
    结果:1 1 1

  • setState处在异步的逻辑中,同步更新状态,同步跟新真实dom
    在这里插入图片描述
    结果:2 3 4

  • setState接受第二个参数,第二个参数是回调函数,状态和dom更新完后会被促发
    在这里插入图片描述
    结果:2 2 2

九、属性(props)(类组件与函数组件)

一、基本使用

props是正常外部传入的,组件内部可以通过一些方式来初始化设置,属性不能被组件自己更改,但是可以通过父组件主动重新渲染的方式来传入新props。
父组件:
在这里插入图片描述
组件中添加属性,{}中可识别js代码,并且识别布尔值需要使用{}。
子组件:(类组件写法)
在这里插入图片描述
在这里插入图片描述

通过this.props拿到父组件传递过来的参数
子组件:(函数组件写法)
在这里插入图片描述
在这里插入图片描述
通过函数接收父组件传递过来的参数props

二、属性验证与默认属性

类组件式写法,在父组件中的子组件传参,在子组件中设置属性验证与默认属性设置
父组件
在这里插入图片描述
子组件
在这里插入图片描述

结果:
在这里插入图片描述
propTypes:属性类型
defaultProps:默认属性

  1. 引入’prop-types’包
  2. 设置静态属性propTypes,通过调用方法来限制输入 的类型是什么
  3. 设置静态属性defaultProps,来设置默认属性是什么
    ** 函数式组件**
    父组件:
    在这里插入图片描述

子组件:
在这里插入图片描述
注意:这里的属性验证的写发只能写在函数外面,即是类名.属性的方式。

结果:
在这里插入图片描述

属性vs状态
相似点: 都是纯js对象,都会触发render更新,都具有确定性(状态/属性相同,结果相同)
不同点:
1.属性能从父组件获取,状态不能
2.属性可以由父组件修改,状态不能
3.属性能在内部设置默认值,状态也可以,设置方式不一样
4.属性不在组件内部修改,状态要在组件内部修改
5.属性能设置子组件初始值,状态不可以
6属性可以修改子组件的值,状态不可以
注意:
1、state 的主要作用是用于组件保存、控制、修改自己的可变状态。 state 在组件内部初始化,可以被组件自身修改,而外部不能访问也不能修击。你可以认为 state 是一个局部的、只能被组件自身控制的数据源。 state 中状态可以通过 this.setstate 方法进行更新,setstate 会导致组件的重新渲染。
2、props 的主要作用是让使用该组件的父组件可以传入参数来配置该组件。它是外部传进来的配置参数,组件内部无法控制也无法修改。除非外部组件主动传入新的 props,否则组件的 props 永远保持不变。
3、没有 state 的组件叫无状态组件 (stateless component),设置了 state 的叫做有状态组件 (statefulcomponent)。因为状态会带来管理的复杂性,我们尽量多地写无状态组件,尽量少地写有状态的组件。这样会降低代码维护的难度,也会在一定程度上增强组件的可复用性。

十、表单中的受控与非受控组件

非受控组件:

使用ref来从DOM节点中获取表单的数据,就是非受控组件。
例如:设置输入框的默认值
在这里插入图片描述
在这里插入图片描述

注:通过value来设置默认值,发现设置之后,input框中的内容不可变(可想像成组件传参方式)。所以设置默认值可以采用defaultValue设置(第一次收控制,之后并不受控制)
在这里插入图片描述
在这里插入图片描述
注:若想给子组件传递表单数据,使用这种方式是不会动态更新的,因为重新渲染react组件是通过state的方式,即使用受控组件的方式。

受控组件:

在这里插入图片描述
value受控,通过结合state的方式来控制变化,结合onChange监听函数(与onInput效果一致),一输入即促发,重新设置且渲染输入框的值。
** 总结**
受控:value 非受控:defalutValue
onChange等同于onInput
注意:广义上的受控与非受控的说法:react组件的数据渲染是否被调用者传递的props完全控制,控制则为受控组件,否则为非受控组件。

十二、父子组件通信

父组件向子组件传递数据,子组件中触发父组件中的方法。
父组件:
在这里插入图片描述
通过写的event事件,传递给子组件
子组件:
在这里插入图片描述
子组件通过this.props拿到传递过来的数据,直接在点击触发该函数事件。
总结:
父传子:属性
子传父:回调函数

例一、

表单域受控组件:
在这里插入图片描述
在这里插入图片描述
通过父组件state封装表单域

表单域ref组件:
在这里插入图片描述
在这里插入图片描述
通过父组件ref获取子组件参数,结合子组件state封装表单域

十三、非父子组件通信

一、订阅发布模式:
在这里插入图片描述

  1. 订阅者与发布者都是多对多模式
  2. 找一个公共的调度中心,使得参与的组件都可调用到
  3. 订阅者要在发布者之前订阅,订阅者即拿到发布者传递的信息,等待被执行。
  4. 发布者发布消息,将所有订阅的消息都执行,调用回调函数。
    二、context状态树传参:
    在这里插入图片描述
  5. 使用const globalContext = React.createContext()创建对象
  6. <globalContext.Provider value={}> </globalContext.Provider> 作为提供者,value中即提供的数据
  7. <globalContext.Consumer></globalContext.Consumer> 作为消费者,被包裹的里面才可以获取到提供者的value数据。并且里面必须使用()=>{},函数里面传参。

十四、插槽的使用

在这里插入图片描述
在引用的子组件中写东西,就是插槽的写法

  1. 在父组件中的子组件中写内容,不同的内容则进行不同的展示
  2. 在子组件中通过this.props.children来进行展示
  3. 若只展示父组件中部分数据,则可以使用this.props.children[0]…方式,因为它是一个数组

十五、生命周期(类组件)

一、初始化阶段:

在这里插入图片描述
componentWillMount:
在这里插入图片描述
render:
在这里插入图片描述
componentDidMount:
在这里插入图片描述
1、componentWillMount只执行一次,16.2之后不推荐使用,要用则改成UNSAFE_componentWillMount,或者放在componentDidMount和constructor中。在此阶段获取不到dom结构。
2、componentDidMount只执行一次
3、render即重新更新即执行
4、执行顺序:componentWillMount(类似vue中create)、render、componentDidMount(类似vue中mounted)。

二、运行中阶段:

在这里插入图片描述
1、componentWillUpdate:拿到更新前的状态,不推荐使用,使用UNSAFE_componentWillUpdate,执行多次。
2、componentDidUpdate:拿到更新前的数据,或者dom节点,执行多次。
componentDidUpdate(prevProps, prevState, snapshot?)
preProps老的属性,preState老的状态

在这里插入图片描述
3、shouldComponentUpdate,组件是否更新。
nextProps新状态,nextState新属性
在这里插入图片描述
例子: 10个盒子会render10次,则通过shouldComponentUpdate减少重复没必要的跟新。在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
4、componentWillReceiveProps,在子组件中使用,父组件重新渲染即执行,最先获得父组件传来的属性,可以利用属性进行ajax或者逻辑处理,把属性转化成孩子自己的状态。(优先级低,容易被打断,有问题!)
![在这里
5、执行顺序:shouldComponentUpdate、componentWillUpdate、render、componentDidUpdate。

三、销毁阶段:

在这里插入图片描述

四、新生命周期的替代

老生命周期的问题
(1) componentWiMount,在ssr中这个方法将会被多次调用,所以会重复触发多遍,同时在这里如果绑定事件,将无法解绑,导致内存泄漏,变得不够安全高效逐步废弃,
(2)componentWiReceiveProps外部组件多次频繁更新传入多次不同的 props,会导致不必要的异步请求
(3)componetWillupdate,更新前记录 DOM 状态,可能会做一些处理,与componentDidUpdate相隔时间如果过长, 会导致状态不太行
新生命周期的替代
1、getDerivedStateFormProps:第一次的初始化组件以及后续的更新过程中(包括自身状态更新以及父传子),返回一个对象作为新的state,返回null则说明不需要在这里更新state。
- 新老生命周期不能共存,指的是componentWillReceiveProps生命周期
- 作用:转化成自己的状态
- 不能再此进行axios请求,需结合componentDidUpdate
- 解决频繁异步请求问题,操作结束后即合并
在这里插入图片描述
2、getSnapshotBeforeUpdate:取代了 componetWillUpdate ,触发时间为update发生的时候,在render之后dom渲染之前返回一个值,作为componentDidUpdate的第三个参数。解决了componetWilUpdate 不必要的问题,新老生命周期不能共存。
在这里插入图片描述
3、PureComponent:会帮你比较新props跟I日的props,新的state和老的state(值相等,或者对象含有相同的属性、且属性值相等),决定shouldcomponentUpdate 返回true 或者false,从而决定要不要呼叫 render function,
注意:如果你的 state或 props「永远都会变』,那PureComponent 并不会比较快,因为shallowEqual 也需要花时间,

十六、Hooks

使用hooks理由
1.高阶组件为了复用,导致代码层级复杂
2.生命周期的复杂
3.写成functional组件,无状态组件,因为需要状态,又改成了class,成本高

一、useState

useState 是一个 React Hook,它允许你向组件添加一个 状态变量。
useState(initialState):按照惯例使用 数组解构 来命名状态变量,例如 [something,
setSomething]

在这里插入图片描述

二、useEffect

useEffect(setup, dependencies?)

setup:必选,处理 Effect 的函数,它选择性返回一个 清理(cleanup) 函数。在初次页面渲染执行,且在每次依赖项变更重新渲染后,将重新运行 setup 函数。在组件从 DOM 中移除后,React 将最后一次运行清理(cleanup) 函数。
dependencies:可选,[dep1, dep2, dep3] 这样内联编写。setup 代码中引用的所有响应式值的列表。响应式值包括 props、state 以及所有直接在组件内部声明的变量和函数。若传空数组,则只会在初始化渲染的时候执行一次。
返回值: undefined。
注意:useEffect在一个组件中可注册多次。
useEffect和useLayoutEffect区别:useLayoutEffect调用时机不同(在虚拟dom中执行),频繁更新会阻塞页面渲染。若要操作dom,则在useLayoutEffect操作。useEffect在页面渲染完之后执行。大部分情况使用useEffect。

例一、

在这里插入图片描述

例二、清除事件等

在这里插入图片描述

三、useCallBack

useCallback 是一个允许你在多次渲染中缓存函数。防止因为组件的重新渲染,导致方法被重新创建,起到缓存作用,只有第二个参数变化了。才重新声明一次。
const cachedFn = useCallback(fn, dependencies)
fn:想要缓存的函数。此函数可以接受任何参数并且返回任何值。React 将会在初次渲染而非调用时返回该函数。当进行下一次渲染时,如果 dependencies 相比于上一次渲染时没有改变,那么 React 将会返回相同的函数。否则,React 将返回在最新一次渲染中传入的函数,并且将其缓存以便之后使用。React 不会调用此函数,而是返回此函数。
dependencies: 不缓存的变量,如果这个参数变化了,则会重新执行次函数,其他改变不会执行,还是缓存之前的函数。
返回值:在初次渲染时,useCallback 返回你已经传入的 fn 函数。在之后的渲染中, 如果依赖没有改变,useCallback 返回上一次渲染中缓存的 fn 函数;否则返回这一次渲染传入的 fn。

用法

  1. 跳过组件的重新渲染
  2. 从记忆化回调中更新 state
  3. 防止频繁触发 Effect
  4. 优化自定义 Hook

例子:在这里插入图片描述

四、useMemo

useMemo是一个 React Hook,它在每次重新渲染的时候能够缓存计算的结果。(类似vue中的计算属性)。
fn:要缓存计算值的函数,可以返回任意类型。React 将会在首次渲染时调用该函数;在之后的渲染中,如果 dependencies 没有发生变化,React 将直接返回相同值。否则,将会再次调用 fn 并返回最新结果,然后缓存该结果以便下次重复使用。
inputs:所有在 fn函数中使用的响应式变量组成的数组。响应式变量包括 props、state 和所有你直接在组件中定义的变量和函数。依赖项数组的长度必须是固定的并且必须写成 [dep1, dep2, dep3] 这种形式。
返回值 :在初次渲染时,useMemo 返回不带参数调用 calculateValue 的结果。在接下来的渲染中,如果依赖项没有发生改变,它将返回上次缓存的值;否则将再次调用 fn,并返回最新结果。

useCallback功能完全可以由useMemo取代,如果你通过使用useMemo返回一个记忆函数也是完全可以的。
useCallback(fn,inputs) is equivalent to useMemo(()=》fn,inputs)
区别:useCallback不会执行第一个参数函数,而是将它返回给你,而useMemo会执行第一个函数并且将函数执行结果返回给你。

用法

  1. 跳过代价昂贵的重新计算
  2. 跳过组件的重新渲染
  3. 记忆另一个 Hook 的依赖
  4. 记忆一个函数

例子:
在这里插入图片描述

五、useRef

useRef 是一个 React Hook,它能帮助引用一个不需要渲染的值。
useRef(initialValue)
initialValue:ref 对象的 current 属性的初始值。可以是任意类型的值。这个参数在首次渲染后被忽略。
返回值 :useRef 返回一个只有一个属性的对象
注意:可以修改 ref.current 属性。与 state 不同,它是可变的。改变 ref.current 属性时,React 不会重新渲染组件。React 不知道它何时会发生改变,因为 ref 是一个普通的 JavaScript 对象。

作用:

  1. 使用用 ref 引用一个值
  2. 通过 ref 操作 DOM
  3. 避免重复创建 ref 的内容

例子一:(计数器)
在这里插入图片描述
例子二:(充当dom节点)
在这里插入图片描述

六、useContext

useContext 是一个 React Hook,可以让你读取和订阅组件中的 context。(组件中通信)
const value = useContext(SomeContext)
SomeContext:先前用 createContext 创建的 context。context 本身不包含信息,它只代表你可以提供或从组件中读取的信息类型。
返回值: useContext 为调用组件返回 context 的值。它被确定为传递给树中调用组件上方最近的 SomeContext.Provider 的 value。如果没有这样的 provider,那么返回值将会是为创建该 context 传递给 createContext 的 defaultValue。返回的值始终是最新的。如果 context 发生变化,React 会自动重新渲染读取 context 的组件。
注意:组件中的 useContext() 调用不受 同一 组件返回的 provider 的影响。相应的 <Context.Provider> 需要位于调用 useContext() 的组件 之上。
从 provider 接收到不同的 value 开始,React 自动重新渲染使用了该特定 context 的所有子级。先前的值和新的值会使用 Object.is 来做比较。使用 memo 来跳过重新渲染并不妨碍子级接收到新的 context 值。

用法

  1. 向组件树深层传递数据
  2. 通过 context 更新传递的数据
  3. 指定后备方案默认值
  4. 覆盖组件树一部分的 context
  5. 在传递对象和函数时优化重新渲染

例子:
在这里插入图片描述

七、reduce

useReducer 是一个 React Hook,它允许你向组件里面添加一个 reducer。用于统一保存状态数据以及处理函数。一般用于结合useContext进行非父子组件通信。
const [state, dispatch] = useReducer(reducer, initialArg, init?)
reducer:用于更新 state 的纯函数。参数为 state 和 action,返回值是更新后的 state。state 与 action 可以是任意合法值。
initialArg:用于初始化 state 的任意值。
返回值 :useReducer 返回一个由两个值组成的数组
dispatch :返回的 dispatch 函数允许你更新 state 并触发组件的重新渲染。它需要传入一个 action 作为参数
注意:reduce中不能写异步

用法

  1. 向组件添加 reducer
  2. 实现 reducer 函数
  3. 避免重新创建初始值

例子一:
在这里插入图片描述
例子二:非父子组件通信
在这里插入图片描述

八、自定义hooks

当我们想在两个函数之间共享逻辑时,我们会把它提取到第三个函数中。必须以use”开头吗?必须如此,这个约定非常重要。不遵循的话,由于无法判断某个函数是否包含对其内部Hook 的调用,React 将无法自动检查你的 Hook是否违反了 Hook的规则。

十七、路由

1、什么是路由?

路由是根据不同的 ur] 地址展示不同的内容或页面。一个针对React而设计的路由解决方案、可以友好的帮你解决Reactcomponents 到URL之间的同步映射关系

2、路由安装

npm install react-router-dom@5

3、路由模式

hashRouter:前端路由模式,带#的路径,不会向后端发起请求
browerRouter:没有#路径,会向后端发起请求要页面,后端没有对应的路由处理路径就404,则需要重新渲染index页面,即会执行前端自己配置的路由信息。

三、一级路由及路由重定向

在这里插入图片描述
Switch:相当于swith函数,只执行一次就不进行后续
/🆔动态路由匹配跳转参数,保存在跳转路径中
Redirect:重定向,exact:精确匹配

四、路由嵌套

在这里插入图片描述
在子组件中写嵌套的路由信息

五、路由跳转方式

声明式导航:
在这里插入图片描述
类似a标签,activeClassName即选中时添加的类名
编程式导航:
在这里插入图片描述
类似window.location.hash,三种写法。被router组件包裹的组件,会获取到router对象。包含hsitory、location、match等。

六、路由拦截

在这里插入图片描述

在路由组件中,render中写处理函数,返回什么则渲染什么组件。

七、WithRouter

若父组件中子组件拿不到location、history这些参数,则在封装的子组件中需要把props传递给子组件才能拿到。
在这里插入图片描述
使用WithRouter组件进行包装,可以跨级拿到history、location、match等属性。
在这里插入图片描述
例一、
在这里插入图片描述
在这里插入图片描述
例二、
在这里插入图片描述

八、反向代理

浏览器有同源策略,不同的服务端地址会存在跨域,则需要采用反向代理模式。
参考文档地址:

https://create-react-app.dev/docs/proxying-api-requests-in-development/

步骤:
在这里插入图片描述
安装完之后要在src目录下创建setupProxy文件:
在这里插入图片描述
若要使用多个代理,则写多个app.use()进行注册即可。

例子:
在这里插入图片描述
在这里插入图片描述

九、CSSModule

为了防止多人合作做项目时,出现样式冲突问题,防止引用重复,则可以将文件夹命名为name.module.css的方式,若想全局引用,则使用name.css形式。注意,在name.module.css中标签形式的写法还是会全局引用,最好还是写成类或者id的形式。
在这里插入图片描述

引入module.css文件的时候,名字会被改写,则直接通过引入的形式,通过对象拿到类名。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

十八、redux

redux功能类似vue中的store,采用flux思想。原理:订阅发布模式。

一、redux设计原则:

  • state以单一对象存储在store对象中,通过store.getState()获取state。
  • state只读(每次都返回一个新对象,深复制)。唯一改变state的方法就是触发action,action是一个用于描述已经发生事件的普通对象。 store.dispatch(action)
  • 使用纯函数reducer执行state更新。Reducers只是一些纯函数,它接收先前的state和action,并且返回新的state.可以复用、可以控制顺序、传入附加参数。Reducers本质是一个函数,用来响应发送过来的actions,经处理将state发生给store。接收两个参数:一是初始化state,二是action。
  • 拥有以下属性和方法:
state应用的数据状态
getState获取数据状态
Dispatch发送action
Subscribe注册监听,Subscribe的返回值注销监听

二、工作流:
图一:
在这里插入图片描述
图二:
在这里插入图片描述

三、具体写法:

1、redux文件中写处理函数:
在这里插入图片描述
通过createStore来创建store,reducer函数来处理store。

2、发布:使用dispatch函数进行发布
在这里插入图片描述
发布中可以使用处理函数(action):去返回dispatch中的对象,写一些复杂的处理逻辑。
action函数:

在这里插入图片描述
action文件中:
在这里插入图片描述
3、订阅:使用subscribe函数进行订阅,getState函数获取发布中的值。
在这里插入图片描述

reducer扩展:
如果不同的action所处理的属性之间没有联系,我们可以把 Reducer 函数拆分。不同的的函数负责处理不同属性,最终把它们合并成一个大的Reducer 即可。
reducers文件一:
在这里插入图片描述
reducers文件二:
在这里插入图片描述
合并到store文件中:使用combineReducers进行合并。
在这里插入图片描述

注意:这种合并的形式会导致获取值的形式发生变化。需要通过store.getState().reducerName.storeName的方式。同时,describle订阅了之后,页面销魂需要把订阅的函数也销毁。
在这里插入图片描述

** 四、redux中间件**
action函数在正常情况下,reducer处理同步很完美。但是它处理不了异步的情况。所以我们需要在action和reducer中间架起一座桥梁来处理异步,这就是middleware。

常用异步中间件:
1、redux-thunk(store.dispatch参数可以是一个函数,直接返回一个函数):
在store文件中:
在这里插入图片描述

在store.dispatch(action), action中:
在这里插入图片描述
2、redux-promise(store.dispatch参数可以是一个函数,函数中直接返回promise对象):
store文件中:
在这里插入图片描述
action文件中:
在这里插入图片描述

十九、react-redux

使用此库,不需要自己去订阅以及发布,更简索。
Provider组件:将store传递给connect函数。
connect:函数将生成一个父组件,进行订阅以及取消订阅,将state以及dispatch函数传递给子组件,总结就是进行父出传子功能。
connect是HOC,高阶组件
Provide组件,可以让容器组件那到state,使用了context
高阶组件的使用:
1、代码复用,代码模块化
2、增删改props
3、渲染劫持
封装connect高阶函数例子:
在这里插入图片描述
例子:
在app.js中使用Provider组件进行包装,将store进行传递到子组件
在这里插入图片描述
使用connect函数进行订阅与发布:
发布:
在这里插入图片描述
订阅:
在这里插入图片描述

redux-presist:持久化存储
下载插件:npm install redux-presist
store文件配置:

  • 本地存储 import storage from 'redux-persist/lib/storage 会话存储 import
  • storageSession from 'redux-persist/lib/storage/session
  • 其中blacklist设置哪些数据不需要存储,因为在项目中,有些数据是没有必要存储的
    store.js:
    在这里插入图片描述
    app.js文件:
    在这里插入图片描述

二十、性能优化-immutable

lmmutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。同时为了避免 deepCopy把所有节点都复制一遍带来的性能损耗,nmutable 使用结构共享,即如果对象树种一个节点发生变化,只修改这个节点和受影响的父节点,其他节点则进行共享。

import {fromJs} from “immutable”
fromJS():全部包装成map对象
toJs():转化为普通js对象,即正常的形态
get(key):获取值 ,可链式调用
set(key,value):设置普通值,可链式调用
setIn(([第一层,第二层...],value):设置所有值,除了数组
updateIn([第一层,第二层...],fn):设置数组值
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
** redux中的使用**
reducer中:
在这里插入图片描述

二十一、mobx(替代redux)

取代redux的一个状态管理工具,类似vue中的store原理。
原则:
在这里插入图片描述

mobx和redux区别:

  1. 对一份数据直接进行修改操作,不需要返回一个新数据,可直接进行操作。
  2. 并非单一的store,可以多个store。
  3. redux默认以js原生对象的形式存储数据,而mobx可以的是观察对象。

具体使用:
1、observable:
普通类型:

const temperature = observable.box(20); //初始化参数
temperature.set(25);//设置参数值
temperature.get();//获取
复杂对象:
一、使用map函数
const map = observable.map({ key: “value”}); //初始化参数
map.set(“key”, “new value”);//设置参数值
map.get(“key”);//获取
二、直接进行设置获取
const list = observable([1, 2, 4]);
list[2] = 3;
const person = observable({
firstName: “Clive Staples”,
lastName: “Lewis”
});
person.firstName = “C.S.”;

2、Autorun
监听函数,即自动执行函数。

autorun(fn)
autorun(() => console.log(sum.get()))

  • 24
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值