安装AntDesign
cnpm install antd --save
创建store仓库
cnpm install --save redux
安装好redux之后,在src目录下创建一个store文件夹,然后在文件夹下创建一个index.js文件
import { createStore } from 'redux' // 引入createStore方法
import reducer from './reducer'
const store = createStore(reducer) // 创建数据存储仓库
export default store //暴露出去
这时候就需要一个有管理能力的模块出现,这就是Reducers;在store文件夹下,新建一个文件reducer.js。
const defaultState = {} //默认数据
export default (state = defaultState,action)=>{ //就是一个方法函数
return state
}
组件获得store中的数据
import store from './store/index'
constructor(props){
super(props)
console.log(store.getState())
}
安装Redux DevTools
如何配置这个Redux Dev Tools插件
import { createStore } from 'redux' // 引入createStore方法
import reducer from './reducer'
const store = createStore(reducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()) // 创建数据存储仓库
export default store //暴露出去
//其实就是加了这样一句话;
//window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
//这句话的意思就是看window里有没有这个方法,有则执行这个方法
创建Action
想改变Redux里边State的值就要创建Action了。Action就是一个对象,这个对象一般有两个属性,第一个是对Action的描述,第二个是要改变的值。
action就创建好了,但是要通过dispatch()方法传递给store。
changeInputValue(e){
const action ={
type:'changeInput',
value:e.target.value
}
store.dispatch(action)
}
store的自动推送策略
store只是一个仓库,它并没有管理能力,它会把接收到的action自动转发给Reducer.
export default (state = defaultState,action)=>{
console.log(state,action)
return state
}
// state: 指的是原始仓库里的状态。
// action: 指的是action新传递的状态。
改变store里的值。我们先判断type是不是正确的,如果正确,我们需要从新声明一个变量newState。(Reducer里只能接收state,不能改变state。),所以我们声明了一个新变量,然后再次用return返回回去。
export default (state = defaultState,action)=>{
if(action.type === 'changeInput'){
let newState = JSON.parse(JSON.stringify(state)) //深度拷贝state
newState.inputValue = action.value
return newState
}
return state
}
让组件发生更新
写一个storeChange方法;重新setState一次就可以实现组件也是变化的。
storeChange(){
this.setState(store.getState())
}
在constructor,写入下面的代码。
constructor(props){
super(props)
this.state=store.getState();
//----------关键代码-----------start
store.subscribe(()=>this.storeChange()) //订阅Redux的状态
//----------关键代码-----------end
}
Redux的小技巧
把Action Types 单度写入一个文件;在src/store文件夹下面,新建立一个actionTypes.js文件,然后把Type集中放到文件中进行管理。
//actionTypes.js
export const CHANGE_INPUT = 'changeInput'
export const ADD_ITEM = 'addItem'
export const DELETE_ITEM = 'deleteItem'
引入组件和Reducer中并使用;然后把对应的字符串换成常量
import { CHANGE_INPUT , ADD_ITEM , DELETE_ITEM } from './store/actionTypes'
把所有的Redux Action放到一个文件里进行管理
编写actionCreators.js文件;在/src/store文件夹下面,建立一个心的文件actionCreators.js,先在文件中引入上节课编写actionTypes.js文件。
实现Redux Action和业务逻辑的分离,可打打提供程序的可维护性。
//actionCreators.js
import {CHANGE_INPUT} from './actionTypes'
export const changeInputAction = (value)=>({
type:CHANGE_INPUT,
value
})
在组件中引入
import {changeInputAction} from './store/actionCreatores'
changeInputValue(e){
const action = changeInputAction(e.target.value)
store.dispatch(action)
}
Redux小坑
-
store必须是唯一的,多个store是坚决不允许,只能有一个store空间
-
只有store能改变自己的内容,Reducer不能改变
Reudcer只是返回了更改的数据,但是并没有更改store中的数据,store拿到了Reducer的数据,自己对自己进行了更新。
-
Reducer必须是纯函数
纯函数定义:如果函数的调用参数相同,则永远返回相同的结果。它不依赖于程序执行期间函数外部任何状态或数据的变化,必须只依赖于其输入参数。
Redux-thunk
什么时候会用到这个插件那?比如在Dispatch一个Action之后,到达reducer之前,进行一些额外的操作,就需要用到middleware(中间件)。在实际工作中你可以使用中间件来进行日志记录、创建崩溃报告,调用异步接口或者路由;它就是对Redux中dispatch的加强。
# 安装
npm install --save redux-thunk
配置:
需要在创建store的地方(/store/index.js文件)引入redux-thunk。
-
引入applyMiddleware,如果你要使用中间件,就必须在redux中引入applyMiddleware.
import { createStore , applyMiddleware } from 'redux'
-
引入redux-thunk库
import thunk from 'redux-thunk'
按照官方文档来写,你直接把thunk放到createStore里的第二个参数就可以了,但以前我们配置了Redux Dev Tools,已经占用了第二个参数。
如果想两个同时使用,需要使用增强函数。使用增加函数前需要先引入compose。
import { createStore , applyMiddleware ,compose } from 'redux'
然后利用compose创造一个增强函数,就相当于建立了一个链式函数
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}):compose
有了增强函数后,就可以把thunk加入进来了,这样两个函数就都会执行了。
const enhancer = composeEnhancers(applyMiddleware(thunk))
全部代码:
import { createStore , applyMiddleware ,compose } from 'redux' // 引入createStore方法
import reducer from './reducer'
import thunk from 'redux-thunk'
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}):compose
const enhancer = composeEnhancers(applyMiddleware(thunk))
const store = createStore( reducer, enhancer) // 创建数据存储仓库
export default store //暴露出去
使用
以前actionCreators.js都是定义好的action,根本没办法写业务逻辑,有了Redux-thunk之后,可以把TodoList.js中的componentDidMount业务逻辑放到这里来编写。也就是把向后台请求数据的代码放到actionCreators.js文件里。那我们需要引入axios,并写一个新的函数方法。(以前的action是对象,现在的action可以是函数了,这就是redux-thunk带来的好处)
import axios from 'axios'
...something...
export const getTodoList = () =>{
return ()=>{
axios.get('...').then((res)=>{
const data = res.data
console.log(data)
})
}
}
现在我们需要执行这个方法,并在控制台查看结果,这时候可以修改TodoList.js文件中的componentDidMount代码。
//先引入getTodoList
import {getTodoList , changeInputAction , addItemAction ,deleteItemAction,getListAction} from './store/actionCreatores'
---something---
componentDidMount(){
const action = getTodoList()
store.dispatch(action)
}
然后我们到浏览器的控制台中查看一下,看看是不是已经得到了后端传给我们的数据,如果一切正常,应该是可以得到。得到之后,我们继续走以前的Redux流程就可以了。
export const getTodoList = () =>{
return (dispatch)=>{
axios.get('https://www.easy-mock.com/mock/5cfcce489dc7c36bd6da2c99/xiaojiejie/getList').then((res)=>{
const data = res.data
const action = getListAction(data)
dispatch(action)
})
}
}
React-Redux
介绍与安装
React-Redux这是一个React生态中常用组件,它可以简化Redux流程。(需要注意的是概念:React、Redux、React-redux是三个不同的东西)。
安装react-redux:
npm install --save react-redux
<Provider>提供器讲解
Provider是一个提供器,只要使用了这个组件,组件里边的其它所有组件都可以使用store了,这也是React-redux的核心组件了。
import React from 'react';
import ReactDOM from 'react-dom';
import TodoList from './TodoList'
//---------关键代码--------start
import { Provider } from 'react-redux'
import store from './store'
//声明一个App组件,然后这个组件用Provider进行包裹。
const App = (
<Provider store={store}>
<TodoList />
</Provider>
)
//---------关键代码--------end
ReactDOM.render(App, document.getElementById('root'));
connect连接器的使用
引入connect,它是一个连接器(其实它就是一个方法),有了这个连接器就可以很容易的获得数据了.
import {connect} from 'react-redux' //引入连接器
这时候暴露出去的就变成了connect了,代码如下。
export default connect(xxx,null)(TodoList);
整体案列
import React, { Component } from 'react';
import store from './store'
import {connect} from 'react-redux'
class TodoList extends Component {
constructor(props){
super(props)
this.state = store.getState()
}
render() {
return (
<div>
<div>
<input value={this.props.inputValue} />
<button>提交</button>
</div>
<ul>
<li>JSPang</li>
</ul>
</div>
);
}
}
const stateToProps = (state)=>{
return {
inputValue : state.inputValue
}
}
export default connect(stateToProps,null)(TodoList);
React-redux的数据修改
要使用react-redux,我们可以编写另一个映射DispatchToProps,先看下面这段代码,你会发现有两个参数,第二个参数我们用的是null。
import React, { Component } from 'react';
import store from './store'
import {connect} from 'react-redux'
class TodoList extends Component {
render() {
// 集中管理
let {inputValue ,inputChange} = this.props;
return (
<div>
<div>
<input value={inputValue} onChange={inputChange} />
<button>提交</button>
</div>
<ul>
<li>JSPang</li>
</ul>
</div>
);
}
}
const stateToProps = (state)=>{
return {
inputValue : state.inputValue
}
}
const dispatchToProps = (dispatch) =>{
return {
inputChange(e){
console.log(e.target.value)
}
}
}
export default connect(stateToProps,dispatchToProps)(TodoList);
把TodoList改为UI组件-提高性能
现在的TodoList组件里没有任何的业务逻辑,只有一个Render方法,这时候就可以把它改为UI组件(无状态组件),UI组件就是一个方法,减少很多冗余操作,从而提高程序运行性能。
import React from 'react';
import store from './store'
import {connect} from 'react-redux'
const TodoList = (props)=>{
// 集中管理
let {inputValue ,inputChange} = this.props;
return (
<div>
<div>
<input value={inputValue} onChange={inputChange} />
<button>提交</button>
</div>
<ul>
<li>JSPang</li>
</ul>
</div>
);
}
const stateToProps = (state)=>{
return {
inputValue : state.inputValue
}
}
const dispatchToProps = (dispatch) =>{
return {
inputChange(e){
console.log(e.target.value)
}
}
}
export default connect(stateToProps,dispatchToProps)(TodoList);
网友评论