React-Redux基础(一):认识 Redux,Redux 的基本用法

首先,什么是 redux,它是干嘛用的?

我们要知道,在一个有点规模的程序里面,不可能只有一个组件,最少都是几百甚至于更多。那么在这种情况下,我们如果希望某些数据能够在组件之间共通,都来使用这一套数据,那么 redux 就可以帮到我们。

redux 是一个状态管理的容器。所谓状态,简单来说就是数据。那 redux 为什么叫做一个容器呢?

其实说白了,数组也好,json 也好,它也是一个容器,只不过它只能在你变量能到达的范围之内使用。而 redux 它是整个程序之内都可以共同来用的。

对于 redux,有两个基础点我们需要先了解一下:

1,redux 可以独立使用。当然,大部分都是和 react 一起配合使用的。

2,redux 是一个单向的数据流。

什么叫单向数据流呢?意思是数据只能过去,是不能回来的。Vue 里面就是一个双向数据流,双向数据流比较易于使用,但是也会造成很多的混乱。

实际上对于真正的大型程序来说,并不是方便最重要,而是你的这个东西严谨而且安全才是最重要的。所以 redux 它更适合于大型的项目。它带来的好处就是比较简单,而且易于测试。那么到此,我们就对 redux 有一个基本的认识了。

接下来,我们就先把第一个事搞明白。到底什么叫单向数据流。

首先,一共涉及到 store,组件,action 和 reducer 这 4 个东西。

第一个就是 store,这个 store 就是 redux 的核心。所有的状态,也就是数据,都会存到 store 这个对象身上。我们如果需要操作数据的话,也需要经过它。(store 其实就是一个 json)

接下来,store 它里面的数据,会被更新到我们的组件上。当然除了组件外,我们也可以用原生的 redux 来做事,所以也可以是原生的代码,只不过大多数情况下我们是跟组件来配合的。

store 它里面的数据一旦发生变化,它会把这个更新,发送给组件,而组件它可以触发这个更新。

比如用户输入了某个东西,点击了什么按钮,这些都会导致数据发生变化,那么这个时候,我们的组件它就可以通过 dispatch 来发出一个 action。

action 是 redux 里面所有对数据修改的一个封装。我们对数据做任何事情,全都是一个 action。(action 其实也是一个 json)

然后这个 action 被 dispatch 派发出去之后,它会被一个 reducer 来接收到。

你可以简单的认为 reducer 就是一个函数,这个函数它负责对数据进行更新。

简单来说,就是有一个 action 过来,被我的 reducer 看到了,那么这时候,这个 reducer 就会执行一遍。每当修改的时候,都会执行一遍。

然后 reducer 执行了之后,它就可以把这个数据,也就是 store 里面存的 state,给修改了。

然后这里面有几个要点:

1,它是单向的。如上图,这个数据只能过去,不能回来。组件想拿数据,只能从 store 这。

2,state 这个状态,所有的修改,只能通过 reducer 来完成。而且你直接去调用 reducer 是不行的,你只能去派发一个 action,然后这个 action 会给到 reducer,它再来做事。

可能你会觉得很烦,直接用不行吗?

之所以 redux 里面有这么多的限制。是因为越是大型的东西,其实它越是严谨,越是严格。如果这也行,那也行,就乱套了。就比如一条马路上没有红绿灯,你想怎么走就怎么走,那这条路肯定比哪都堵。

现在我们就大概的了解了 redux 它里面的一些设计思想以及它里面涉及到的一些东西。

接下来用一用,就知道怎么回事了。

首先第一件事,先安装:npm install redux -D

现在我们是不配合 react 来用的,我们原生的去用 redux。下一篇博客在来看下怎么和 react 配合来用。

所以我们先注释掉 index.js 里面的内容。

第一步,引入 createStore,从名字就可以看出来,它是来帮助我们来创建一个 Store 对象的。

然后,我们还需要另外一个东西 reducer

1,它是一个函数。(名字叫啥都行,只要你自己认识就行)

2,每当状态更新的时候,它都会去执行。换句话来说,它里面所有的状态都是通过函数的执行来更新的。

reducer 它里面有2个参数,是定死的:

一个是 state,现在的状态,也就是当前的数据。

另一个是 action,就是这一次我需要你做什么。就比如 state 是一个数组,而 action 可以是增加一个 item,或者修改一个 item。

所以 state 就是当前的数据,而 action,就是这次我要干什么。并且 state 和 action,其实都是一个 json。

那么这2个东西知道了之后,先不管别的,现在我们先来考虑一件事:

这个数据,它是不是得有一个初始化的过程?它第一次得能出来?

所以我们可以直接返回一个 json。

这就是一个最简单的初始数据。

然后下一步,就是创建 store:

实际上来说,到这为止,我们就已经完成了 store 的创建。

然后我们就来看看 store 能干什么。

简单来说,你可以从它里面来拿数据。它里面有个函数 getState,可以给你返回一个目前的状态。

那么接下来的一个问题就来了,我现在想要修改这个数据。

我们需要通过 dispatch 来派发一个 action 出去,然后 action 就可以帮助我们来执行 reducer。

那么修改应该怎么做呢?还是通过 store,它里面有个 dispatch 函数。

store.dispatch 里面就接收一个参数,它是一个 action,说白了这个 action 就是个 json。

然后在这个 action 里面,没有什么特别的要求,就一个,你必须得有一个 type 属性。

比如 type : 'setname'

接下来,你可以想象,如果你要修改用户名的话,肯定是需要告诉它改成什么。

那这时候,你在加别的参数,名字都是随便取的。比如加个 value: '大木2'。

然后我们一起来看看 action 长啥样:

其实 reducer 函数里面的这个 action,就是你在 store.dispatch 里面传的这个 json。

可以看到,reducer 执行了两次。

第一次 type 的值很奇怪,这个是第一次执行,初始化。因为我们的数据它不可能等到你用的时候再去初始化。

在你去创建 createStore 的时候,redux 就会自动的来调用一次 reducer,代表的是初始化。

而接下来,第二次执行,这个就是你执行的 store.dispatch。你通过 dispatch 来派发一个 action,所以它出来的 action 就是你传的那个 json。

那么具体来说,怎么改呢?我们可以用 switch。

我们首先判断下 action.type 是什么,因为这个 type 就代表了我们到底想做什么。

然后接下来,我们就来看下,其实现在我们是有两种 type 的:一个是我们自己定的 setname,另一个就是初始化的 type。

所以我们可以写成 default,因为一大堆乱七八糟的字符串,太长了,我们不太好写,而且你也不能保证它是不变的。

同时还能匹配到未知的 action,比如说有人代码写错了,这时候 default 就可以匹配到。

所以在 default 的时候,我们就返回一个初始数据。而当 setname 的时候,我们要给它返回一个修改后的新数据

注意!如果我们这么写,这个时候,其实你是违背了它本身的意愿的。

按照它的规定,要求必须得是一个全新的数据。

所以,我们可以这么写:

这里错的原因,是因为不是全新的,对的原因是因为它是全新的。这么大动干戈,是为什么呢,直接改不行吗?

其实,如果计算机里面出现了我们无法理解的事情,那么一定就是两个原因,要么是因为安全性,要么就是因为性能。

那么在这,它是出于性能考虑的。

首先,我们用 redux 一定不是只管理几个数据的,可能几百上千个都有。那么这个时候,如果它不是全新的,那这时候 redux 需要付出额外的劳动。因为它需要把你这个数据,从里到外整个都彻底检测一遍。只有这样,它才知道哪个数据变了,哪个数据没变。

然后,如果全都没变的话,那么这个时候它就决定不更新。而如果变了,它还要挑出来,是这个变了,还是那个变了。因为哪个变了,它还要去具体通知用这个数据的组件。

所以为什么 redux 要求你必须得返回一个全新的数据出来,就是因为出于性能方面的考虑。

因为如果这样做的话,它就可以很简单的,直接用一个等号,就能判断你这个数据变没变。

如果没变,就还是原来的对象。而如果变了,它在具体检查哪些东西不一样。

因为对于一个大型的数据结构来说,如果你去做这个深度检查,将是及其耗费系统资源的,所以 redux 才选择这样做。

创建一个对象的性能开销,比检查一个对象,去它里面做深度检查的开销,要小的多。

接下来还有另外一件事,现在这个状态写在这里是比较麻烦的,因为写在这不明显,我们可以换成默认参数的写法:

这样,别人看到 reducer,就能知道初始数据是怎样的。

然后我们来看看,到底有没有变:

name 变成了大木2,说明我们的修改是成功的。

然后我们还有一个点要注意下:store.getState() 它 get 出来的是一个不动的数据,什么意思呢?

可以看到,是没变的。

这是因为我们每次都会返回一个新数据,所以你这个 getState 它之前出来的那个东西,就已经不能用了。

所以这种情况下,你必须得重新的再来 get 一遍,才能够获取到最新的状态。

这个是我们用 redux 必须要注意的一点。

我们现在已经了解了最基本的东西,但是现在还有一个最重要的点,那就是你想象一下:

现在是我主动过来获取数据,能得到最新的,这个当然是对的。但是如果我程序非常庞大,我根本就不知道你这个数据变没变,那我怎么才能知道你数据变了。这是我需要知道的,也是需要我去做的。

所以我们需要知道一个东西,它对我们用 redux 非常的重要。

就是 store 里面的 subscribe,它翻译过来就是订阅的意思。

它其实有点像事件,比如我写了一个 window.onload 事件,那么我就知道现在加载完成了。但你其实是不知道 window.onload 到底在什么时间会发生。因为页面加载是不好说的。如果用户网速快,1秒就加载完了。如果网速不好,有可能加载不完,就出不来。所以在这种情况下,就需要一个类似于事件的机制。

这个在 store 里面就叫做 subscribe。就是每当有数据变化的时候,它就会通知你。

我们来稍微的试一下:现在我们添加一个新的 type: 'addage'

我们在 addage 里面用的不是 value,而是 n,因为前面也说过,除了 type 以外的东西,随便叫什么都是你自己定的。

这里需要注意的是,在这里我们做了 3 次 dispatch,每次做完 dispatch 之后,我们并没有去 getState,但是你会发现,它也能出来:

可以看到,其实它就是靠订阅出来的。

所以到此为止,我们就了解了 redux 它里面的一些最基本的用法。

那么我们稍微的总结一下:

redux 主要的功能就是用来管理数据。

它有个函数:function reducer(){ }

函数名可以随便取,并且它里面有两个参数,一个是 state,一个是 action。

简单来说,state 就是到目前为止的状态,action 是我这次要做的工作。(state 和 action 都是一个 json)

reducer 函数本身的作用就是,用来把你的 action 和 state 合并在一起,生成一个新的结果。

在 reducer 里面,我们一般习惯于放一个 switch,根据它的 action.type 不同,来做不同的事。这个 action 里面的 type 也是我们自己去定义的。

并且在最后的 default 就把 state 给直接 return 出去。

这是因为我们可以做数据的初始化,因为初始化的 type 之所以会写成 '@@redux/INITl.n.8.a.h.m' 这么复杂,就是为了防止和你写的 type 冲突。

最后,最重要的一点就是,千万不要直接把 state 里面的东西给改了,然后原封不动的还是把这个 state 给 return 出去,这个是会出大事的。我们一定要 return 一个新的对象。

发布了78 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43921436/article/details/105410252