Redux 基本介绍
State
:React中的状态是制度对象,不可直接修改
Reducer
:基本函数,用于对State的业务处理
Action
:普通对象,用于描述事件行为,改变State
Redux 解决单项数据流的问题 , 项目中共享全局数据
Redux 工作流
Redux 安装
-
npm 安装
npm install redux --save
npm install react-redux --save -
yran 安装
yarn add redux
yarn add react-redux
Redux 调试工具安装
- 浏览器安装
Redux Devtools
扩展 - npm install redux-devtools-extension --save
- yarn add redux-devtools-extension
Redex 集成
创建
Action
模块
创建Reducer
模块
创建Store
模块
通过connect
方法将React组件和Redux连接起来
添加Provider
作为项目的跟组件,用于数据的存储
Redux 集成具体操作步骤
- 在Action中定义index.js
/**
* Action 类型
*/
//定义类型名
//第2种方式.这里可以在外部定义type的所有内容 例如:import { SWITCH_MENU } from "./type";
export const type={
SWITCH_MENU:'SWITCH_MENU',
}
//触发操作方法就像Vuex的mutations的方法,menuName就是修改的名称 type.类型名称固定定义方式
export function switchMenu(menuName) {
return{
type:type.SWITCH_MENU, //第2种方式 : type:SWITCH_MENU,
menuName
}
}
- Reducer 中定义index.js
/**
* Reducer 数据处理
*/
import {type} from "./../action";
//初始化常量状态
const initialState = {
menuName: '首页'
}
//值的修改操作在这里进行
export default (state = initialState, action) => {
//这里可以做类型判断可以进行多个值的操作
switch (action.type) {
//判断传入值的类型,如果时候menu则赋值action.menuName
case type.SWITCH_MENU:
return{
...state,//原来的值,不能清空原有的值。因为数据内可能还有别的数据以免误操
menuName: action.menuName//新的值
}
break;
default:
return state;//没有任何设置的数据的时候这里要返回state的默认值,否则系统找不到初始数据报错。也可以在mapStateToProps 内部做初始化数据定义,但一定要有初始化的数据
break;
}
}
- store中定义index.js
/**
* 引入creatStore 创建store
*/
//创建store工厂
import {createStore} from 'redux'
//引入reducer 业务处理方法
import reducer from '../reducer'
//devtools 调试工具使用
import {composeWithDevTools} from 'redux-devtools-extension'
//导出新创建的数据源(第一个参数是reducer方法,4.0以后版本不能使用第二个参数可以是调试工具的插件方法)
//export default ()=>createStore(reducer,composeWithDevTools())
export default ()=>createStore(reducer)
- 入口文件index.js 中创建根组件
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Route from './router'
//提供数据源
import {Provider} from 'react-redux'
import configStore from './redux/store'
import * as serviceWorker from './serviceWorker';
const store=configStore()
ReactDOM.render(
//Provider组件包裹根组件,并且传入store数据源对象,也可以在组建中包裹
<Provider store={store}>
<Route/>
</Provider>
,document.getElementById('root')
);
serviceWorker.unregister();
- 组件页面连接Redux,修改数据
import React from 'react'
import './index.less'
import {Menu, Icon, Switch} from 'antd';
import {NavLink} from 'react-router-dom'
//导入连接方法和action方法
import {connect} from 'react-redux'
import {switchMenu} from './../../redux/action'
import MenuConfig from '../../config/menuConfig'
const {SubMenu} = Menu;
class NavLeft extends React.Component {
constructor() {
super()
this.state = ({
theme: 'dark'
})
}
componentWillMount() {
const menuTreeNode = this.renderMenu(MenuConfig)
this.setState({
menuTreeNode
})
}
handleClick = (item) => {
//使用dispatch 修改数据
const {dispatch} = this.props
dispatch(switchMenu(item.item.props.title))
// console.log(item.item.props.title)
}
renderMenu = (data) => {
if (!data) return false
return data.map((item) => {
if (item.children) {
return (
<SubMenu title={item.title} key={item.key}>
{this.renderMenu(item.children)}
</SubMenu>
)
}
return (
<Menu.Item title={item.title} key={item.key}>
<NavLink to={item.key}>{item.title}</NavLink>
</Menu.Item>
)
})
}
render() {
return (
<div className="nav-left-wrap">
<div className="left-logo">
这是logo
</div>
<div>
<Menu
onClick={this.handleClick}
// mode={this.state.mode}
theme={this.state.theme}
>
{this.state.menuTreeNode}
</Menu>
</div>
</div>
)
}
}
//这里把Redux和组件连接起来导出
export default connect()(NavLeft)
- 调用数据
import React from 'react'
import {Row, Col} from 'antd'
import './index.less'
import Utils from '../../utils/utils'
import axios from '../../axios'
import {connect} from 'react-redux'
class Header extends React.Component {
constructor() {
super()
this.state = ({
username: '在水一方'
})
}
componentWillMount() {
setInterval(() => {
let sysTime = Utils.formateDate(new Date().getTime())
this.setState({
sysTime: sysTime
})
}, 1000)
this.getWeatherApiData();
}
getWeatherApiData() {
let city = '北京'
let url = "http://api.map.baidu.com/telematics/v3/weather?location=" + encodeURIComponent(city) + "&output=json&ak=UjymBYD3091SXF9ZW5FwpDlG"
axios.jsonp({
url: url
}).then((res) => {
let weather = res.results[0].weather_data[0]
console.log(weather)
this.setState({
dayPictureUrl: weather.dayPictureUrl,
weather: weather.weather
})
})
}
render() {
return (
<div className="header-wrap">
<Row className="header-top">
<Col span={24}>
<span>欢迎, {this.state.username}</span>
<a href="#"> 退出</a>
</Col>
</Row>
<Row className="breadcrumb">
<Col className="bread-title" span={4}>
{/*调用数据*/}
{this.props.menuName}
</Col>
<Col className="bread-weather" span={20}>
<span>{this.state.sysTime}</span>
<span>
<img src={this.state.dayPictureUrl} alt=""/>
<span>{this.state.weather}</span>
</span>
</Col>
</Row>
</div>
)
}
}
// 导出数据导到组件中
const mapStateToProps = state => {
console.log(state)//这里是返回的{menuName:内容对象}
return {
menuName: state.menuName
}
}
export default connect(mapStateToProps)(Header)