Redux知识总结一(一篇就能搞明白redux的用法)
Redux知识总结一(一篇就能搞明白redux的用法)
一、什么是Redux?
官网:Redux 是 JavaScript应用的状态容器,提供可预测化的状态管理;
- Javascript应用:是指任何Javascript构建的项目,而不是仅仅是React框架构建的项目,当然他们搭配用起来更加顺手;
- 状态容器:react项目中的state抽离出来集中在对象树状结构中store(状态容器),一个项目只能有一个store(状态容器);
- 可预测性:对于状态的更新变化都是通过纯函数进行操作的,纯函数的核心就是不管传入什么参数,都不会影响改变你传入参数的值;也就是每个新的state都会在旧的state进行产生,而且还不改变旧的state,这就是可预测性;
总结:redux是基于facebooke的flux架构建立的框架,因为flux数据只能在一个方向流动的特性(单向性),数据的流向就是Model(State)->view;Flux架构图如下:
注意:一个项目中一般只有一个store(状态容器),项目中所有的state都集中在store中进行管理;
二、为什么用Redux?
先谈谈react,react是由facebook公司开源的前端框架;主要用于构建前端界面,将项目中的前端界面进行组件化处理,也就是说react是解决DOM层面上的抽象层;对于一个完整的前端项目来说,这样是仅仅不够的,它并没有很好的解决组件之间的通信,只通过形式props实现了简单结构的组件通信,对于复杂结构的组件,如果进行采用props形式实现通信,会使整个项目变得难以维护,项目结构混乱;因此诞生出了另一套解决方案:基于Flux架构实现的Redux状态管理框架;
Redux知识介绍:
- “工欲善其事必先利其器”,在介绍Redux之前,先用create-react-app脚手架工具搭建出基本的react项目;
create-react-app介绍链接:https://github.com/facebook/create-react-app
- 如果对React不熟的小伙伴可以参考以下链接学习;
react学习链接:https://zh-hans.reactjs.org/tutorial/tutorial.html
准备好以上知识点,就可以开始我们的Redux之旅了;在这先了解下纯函数;
纯函数:是指在函数中只依赖其参数,并且不会改变所传入的参数,也就是没有副作用的情况下称之为纯函数;代码如下:
/**
**案例一:函数不止依赖于函数参数
**不属于纯函数,setName函数引用了外部变量age,
**不符合“只依赖参数”这个条件
**/
var name="张三";
var age=26;
function setName(name){
str="姓名:"+name+";年龄:"+age;
return str;
}
setName(name);
/**
**案例二:改变外部环境,产生副作用
**不属于纯函数,setName函数改变了外部变量name的
**的,也就是影响了外部环境,产生了副作用;
**/
var name="张三";
function setName(name){
name="李四";
console.log(name);
return name;
}
setName(name);
//纯函数来了
var name="张三";
function setName(name){
var newName=name;
newName="李四";
return newName;
}
setName(name);
redux化繁为简学习:
1、基本了解redux运作机制
redux中state属于状态容器,用来存放相应的数据状态,然后在自定义Action规则,它是把数据从应用传到 store 的有效载荷。属于 store 数据的唯一来源。你可以通过 store.dispatch() 将 action 传到 store。执行reducer纯函数进行数据状态更改;其中store是将它们连接起来的概念化的标识;redux具体运行机制如下图所示:
先了解redux基本运行机制图解。如图所示:
2、利用readux实现标签动态增减
1.通过create-react-app搭建基本项目结构,并通过yarn add redux命令安装redux npm包(cnpm install --save redux)也可以安装,完善项目基本结构;如下图示:
2.利用Action创建函数创建相应的Action,actions.js文件代码如下所示:(Action部分)
/**redux/actions.js文件代码**/
const ADD_TAG="TAG_ADD";
const DEL_TAG="TAG_DEL";
//新增标签Action
export const addTag=(payload)=>{
return {
type:ADD_TAG,
payload:payload
}
}
//移除标签Action
export const delTag=()=>{
return {
type:DEL_TAG
}
}
3.定义标签初始数据状态,state.js文件代码如下所示:(state部分)
/**redux/state.js文件代码**/
export const InitTagState=[{
"id":"001",
"name":"标签一"
}];
4.使用纯函数模式创建reducer处理机(个人认为它就是处理state的处理机),reducer.js文件如下所示:(reducer部分)
/**redux/reducer.js文件代码**/
import {initTagState} from "./state";
import {ADD_TAG,DEL_TAG} from "./actions";
export const TagReducer=(state=initTagState,data)=>{
let new_arr=[];
new_arr=[].concat(state);
switch(data.type){
case ADD_TAG: //新增标签
new_arr.push(data.payload);
return new_arr;
case DEL_TAG: //删除标签
new_arr.splice(0,1);
return new_arr;
default:
return new_arr;
}
}
5.到这里redux系统架构基本完成了,接下来就需要将它们关联起来形成概念化的store了;index.js代码如下
import {createStore,combineReducers} from "redux";
import {TagReducer} from "./reducer";
/*
* 多个reducer汇总的写法(注释区域)
* 需要用combineReducers方法关联形成一个大的reducer
* 只有一个就没有必要用combineReducers方法
*/
// const allReducers={
// tInfo:TagReducer,
// //...
// }
// const reducers=combineReducers(allReducers);
// const store=createStore(reducers);
/*单个写法*/
const store=createStore(TagReducer);
export default store;
6.最终篇,只要通过subscribe方法,将redux与项目主入口文件index.js关联起来即可;根目录下index.js文件代码如下:(index.js属于项目入口文件)
/*根目录中index.js文件*/
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import store from "./redux";
const render=()=>{
ReactDOM.render(<App />, document.getElementById('root'));
};
render();
const unsubscribe=store.subscribe(()=>{
render();
});
serviceWorker.unregister();
7.组件功能实现文件App.js,代码如下:(App.js属于组件入口文件)
import React, { Component } from 'react';
import store from "./redux";
import {addTag,delTag} from "./redux/actions";
import './App.css';
class App extends Component {
addTagFuns=()=>{
const obj={
"name":"标签二"
};
store.dispatch(addTag(obj));
}
delTagFuns=()=>{
store.dispatch(delTag());
}
render() {
const tag_list=store.getState();
let tag_com=tag_list.map((item)=>{
return (<span class="tag">{item.name}</span>);
})
return (
<div className="App">
<div>
<button type="button" onClick={this.addTagFuns}>新增标签</button>
<button type="button" onClick={this.delTagFuns}>删除标签</button>
</div>
{tag_com}
</div>
);
}
}
export default App;
subscribe(funs)这个函数是用来去订阅 store 的变化,你每次对store进行 dispatch(action) 都会触发 subscribe 注册的函数调用,这个在实际情况不是必须要的,看自己的应用场景,如果你想store变化后view视图也要跟着变化,那么就需要全局订阅store变化;