Redux应用场景
redux和vue中的vuex是类似的,他们的使用都是为了使得组件之间数据的通信和实现良好的代码结构。
但并不是说做react的项目就一定需要使用redux,因为如果项目的通信简单,那么完全没有没有必要。 而如果:
- 用户的使用方式复杂
- 与服务器大量交互,或者使用了WebSocket
- View需要从多个来源获取数据
- 则需要使用redux,即多交互、多数据源。
另外,从组件的角度来看,如果某个组件的状态需要共享、某个状态需要在任何地方都可以拿到、一个组件需要改变全局状态、一个组件需要改变另一个组件状态(实际上前面说四者所提到的都是组件间的通信)都是需要redux的。
如果对于上述几种方式也不适用redux,那么状态的管理就非常混乱 。
Redux基本概念
首先,我们先看个图:
store
首先我们先创建一个store文件
## index.js
import { createStore } from 'redux'
const store = createStore()
export default store
复制代码
createStore 的作用就是为了生成一个store对象。
store我们已经创建好了,打个比方:此时的store相当于图书馆的管理员,但是这个管理员记不住到底要怎么管理这些书籍,她需要一个小笔记本来帮助她来管理这些数据。所以,在创建这个管理员(store)的同时也要把这个小笔记本(reducer)给这个管理员(store),要不然她都不知道怎么管理这些书籍(数据)
接下来怎么创建笔记本(reducer)呢?
reducer
首先我们要创建一个名叫reducer.js的文件。
reducer相当于存储图书馆的所有书籍(数据),以及如何处理书籍(数据),所以这个笔记本要记很多内容
## reducer.js
const defaultState = {
inputValue: '',
list: ["javaScript", 'react', 'vue', 'jquery']
}
export default (state = defaultState, action) =>{
return state
}
复制代码
这里的defaultState就是存储图书馆的所有书籍(数据),然后将defaultState赋值给state后将statereturn出去
这样我们就创建了个笔记本啦!下面就是如何将管理员(store)和笔记本(reducer)连接起来
首先我们需要在index.js引入reducer文件
import { createStore } from 'redux'
import reducer from './reducer'
const store = createStore(reducer)
export default store
复制代码
代码写到这,管理员(store)就知道这个图书馆有多少书(数据),也可以到笔记本(reducer)里查看了
接下来我们就可以在组件里面使用store了
组件里使用store的数据
将index.js文件引入组件中,利用store.getState()来获取store里面的数据
constructor(props){
super(props)
this.state = {...store.getState()}
}
复制代码
这样就可以简单的从store里面获取数据显示在页面上了
但是,有时候我们的需求往往没有这么简单,现在我有个input框的值是从store里获取的,需要通过改变store然后再显示到页面上,那么我们要怎么告诉store 要改变数据呢?
action
首先我们需要监听input框的变化的函数handleChange。
handleChange(e) {
const action = {
type: "change_input_value",
value: e.target.value
}
store.dispatch(action)
}
复制代码
action从表面理解就是一个动作。这个action是以一个对象的形式,里面有个type(意思是告诉store这个action是要做什么样的事情),value(改变的值)
这时候这个action已经创建了,就需要调用dispatch来把action发送给store
这个时候action已经传给了store,但是store不知道该怎么处理这个数据,这时候他需要查这个笔记本(reducer),并且他要拿当前store里面的数据和接受到的action去查找这个笔记本(reducer),所以这个时候store要做个事情,就是要拿当前store里面的数据和接收到的这个action转发给reducer,然后reducer告诉store该做什么(很好的事情就是,store接收到action会自动将数据转发给reducer)
Reducer
当reducer拿到了action就会去找到对应action要做的事情,这个时候action里的type就起作用了
const defaultState = {
inputValue: '',
list: ["javaScript", 'react', 'vue', 'jquery']
}
export default (state = defaultState, action) =>{
if(action.type === 'change_input_value'){
const newState = {...state}
newState.inputValue = action.value
return newState
}
return state
}
复制代码
reducer有个限制:reducer可以接收state 但是绝对不可以改变state 所以要深复制state给newState,然后将action.value 赋值给newState.inputValue,对应的值改变之后返回一个新的newState给store,store接收到这个newState时候,会将旧的state替换掉
到这里你以为结束那就是错了,实际情况是store里面数据改变了,但是组件里的数据还没有改变!!!
subscribe
最后一步就是要我们在组件里订阅store:store.subscribe(),当store里面的数据发生变化时subscribe这个函数就会被触发, 我们可以利用subscribe里面加个函数handleStoreChange,在函数handleStoreChange里面执行this.setState(store.getState()),这个时候store里面的数据就和组件里state的数据保持一致了
constructor(props){
super(props)
this.state = {...store.getState()}
this.handleStoreChange = this.handleStoreChange.bind(this)
store.subscribe(this.handleStoreChange)
}
handleStoreChange() {
this.setState(store.getState())
}
复制代码