redux笔记

安装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小坑

  1. store必须是唯一的,多个store是坚决不允许,只能有一个store空间

  2. 只有store能改变自己的内容,Reducer不能改变

    Reudcer只是返回了更改的数据,但是并没有更改store中的数据,store拿到了Reducer的数据,自己对自己进行了更新。

  3. Reducer必须是纯函数

    纯函数定义:如果函数的调用参数相同,则永远返回相同的结果。它不依赖于程序执行期间函数外部任何状态或数据的变化,必须只依赖于其输入参数。

Redux-thunk

什么时候会用到这个插件那?比如在Dispatch一个Action之后,到达reducer之前,进行一些额外的操作,就需要用到middleware(中间件)。在实际工作中你可以使用中间件来进行日志记录、创建崩溃报告,调用异步接口或者路由;它就是对Redux中dispatch的加强。

# 安装
npm install --save redux-thunk

配置:

需要在创建store的地方(/store/index.js文件)引入redux-thunk。

  1. 引入applyMiddleware,如果你要使用中间件,就必须在redux中引入applyMiddleware.

    import { createStore , applyMiddleware } from 'redux'
  2. 引入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);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值