1、什麼是Redux
Redux 是React生態中重要的組成部分。很多人都說,簡單的應用可以不用此工具。但是我個人認爲,中小型應用使用的話,可以使文件結構更加規範,代碼可讀性更強。因爲React提出將展示組件與容器組件分離的思想,所以降低了React 與Redux之間的耦合度。
Redux是一個流行的JavaScript框架,爲應用程序提供一個可預測的狀態容器。Redux基於簡化版本的Flux框架,Flux是Facebook開發的一個框架。在標準的MVC框架中,數據可以在UI組件和存儲之間雙向流動,而Redux嚴格限制了數據只能在一個方向上流動。 見下圖:
在Redux中,所有的數據(比如state)被保存在一個被稱爲store
的容器中 → 在一個應用程序中只能有一個。store
本質上是一個狀態樹,保存了所有對象的狀態。任何UI組件都可以直接從store
訪問特定對象的狀態。要通過本地或遠程組件更改狀態,需要分發一個action
。分發在這裏意味着將可執行信息發送到store
。當一個store
接收到一個action
,它將把這個action
代理給相關的reducer
。reducer
是一個純函數,它可以查看之前的狀態,執行一個action
並且返回一個新的狀態。
Redux的運行原理
store中重要的方法
2、配置Redux
配置Redux開發環境的最快方法是使用create-react-app
工具。在開始之前,確保已經安裝並更新了nodejs
,npm
。
npm install redux
創建store目錄,在store目錄下新建index.js文件,鍵入以下內容:
import {createStore} from 'redux';
import reducer from './reducer';
const store = createStore(reducer);
export default store;
在store目錄下創建reducer.js文件,鍵入以下內容:
const defaultState = {
inputValue:'',
list:[]
}
//reducer可以接收state,但是不能修改state
export default (state = defaultState,action) => {
return state;
}
在組件中就可以使用store的數據
import React,{Component} from 'react';
import store from './store/index';
class TodoList extends Component{
constructor(props){
super(props);
this.state = store.getState();
this.handleStoreChange = this.handleStoreChange.bind(this);
store.subscribe(this.handleStoreChange);
}
handleStoreChange(){
this.setState(store.getState());
}
render(){
return (
<div>
<input type='text' value={this.state.inputValue}/>
<button onClick={this.handleClick}>提交</button>
<ul>
{this.state.list.map((item,index)=>{
return (
<li key={index}>{item}</li>
);
})}
</ul>
</div>
);
}
}
export default TodoList;
3、TodoList案例
TodoList.js
import React,{Component} from 'react';
import store from './store/index';
import {DELETE_TODO_ITEM,CHANGE_INPUT_VALUE,ADD_TODO_ITEM} from './store/actionType'
class TodoList extends Component{
constructor(props){
super(props);
this.state = store.getState();
this.handleChange = this.handleChange.bind(this);
this.handleStoreChange = this.handleStoreChange.bind(this);
this.handleClick = this.handleClick.bind(this);
store.subscribe(this.handleStoreChange);
}
handleChange(e){
const action = {
type:CHANGE_INPUT_VALUE,
value:e.target.value
}
store.dispatch(action);
}
handleStoreChange(){
this.setState(store.getState());
}
handleClick(){
const action = {
type:ADD_TODO_ITEM
}
store.dispatch(action);
}
handleClickItem(index){
const action = {
type:DELETE_TODO_ITEM,
index:index
}
store.dispatch(action);
}
render(){
return (
<div>
<input type='text' value={this.state.inputValue} onChange={this.handleChange} />
<button onClick={this.handleClick}>提交</button>
<ul>
{this.state.list.map((item,index)=>{
return (
<li key={index} onClick={this.handleClickItem.bind(this,index)}>{item}</li>
);
})}
</ul>
</div>
);
}
}
export default TodoList;
store/index.js
import {createStore} from 'redux';
import reducer from './reducer';
const store = createStore(reducer);
export default store;
store/reducer.js
import {DELETE_TODO_ITEM,CHANGE_INPUT_VALUE,ADD_TODO_ITEM} from './actionType'
const defaultState = {
inputValue:'',
list:[]
}
//reducer可以接收state,但是不能修改state
export default (state = defaultState,action) => {
console.log(state,action);
if(action.type === CHANGE_INPUT_VALUE){
const newState = state;
newState.inputValue = action.value;
return newState;
}
if(action.type === ADD_TODO_ITEM){
const newState = state;
newState.list.push(newState.inputValue);
newState.inputValue = '';
return newState;
}
if(action.type === DELETE_TODO_ITEM){
const newState = state;
newState.list.splice(action.index,1);
return newState;
}
return state;
}
store/actionType.js
export const CHANGE_INPUT_VALUE = 'change_input_value'
export const ADD_TODO_ITEM = 'add_todo_item'
export const DELETE_TODO_ITEM = 'delete_todo_item'
核心API:
- createStore 創建store
- store.dispatch 派發action,把數據上傳到Store中
- store.getState 獲取store中所有的數據內容,但是Store中的數據發生變化時,組件不會知道
- store.subscribe 監聽Store中的數據變化,Store中的數據一旦發生變化,該方法就會被執行