redux核心概念
- components View react页面
- Action 如果需要修改store的数据必须派发一个动作,它的参数接收一个对象,对象里面必须要有一个type属性,表示动作的类型,第二个属性是你传入的值
- Reducer 它必须是一个纯函数,来处理store数据的变化,它接收两个参数 一个是state 上一次的数据, 一个是action . 特别注意的是 不能在这里面修改 state数据或者action数据
- Store 仓库 存放state数据 它是链接action与reducer的桥梁 它的实例对象上有些方法,需要去记住它.
getState() 获取当前仓库的 state 数据
dispacth(action) 派发一个动作
subscribe(cb) 监听仓库数据的变化,如果仓库数据有变化,这个回调函数就会执行
unsubscribe(cb) 取消监听 当仓库的数据发生改变的时候 subscribe里面的回调函数会触发,重新返回一个函数 这个函数需要在 componentswillunmount() {}这个生命周期钩子函数里面执行,执行之后就当组件销毁的时候,componentswillunmount()生命周期钩子函数会执行里面的 回调函数也会执行就取消订阅了.
- ActionTypes
动作类型常量
- 如果动作类型是一个字符串的话.出现bug 会非常恶心.
- 作用只是解决字符串写错之后,调试bug 非常困难的问题
- ActionsCreates
- 动作生成器
- 就是一个函数这个函数调用之后,返回一个动作的对象
7.安装 redux
npm install -- save redux || yarn add redux
拆分主reducer, 每个模块的状态都在reducer里面,将每个模块的状态拆分出去,在主的reducer文件中进行引用, 这时就要使用 redux里面的combineReducers方法,这个方法
在 主reducer.js文件中 调用redux的combineReducers方法,返回一个reducer纯函数 并且把它暴露出去
8. redux的中间件
可以阮一峰学习文档参考链接
http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_two_async_operations.html
中间件主要的作用就是帮助我们实现异步代码
之前动作一旦被派发,是直接到了 reducer 的纯函数里面,加上中间件之后,动作派发之后,首先会经过中间件来处理,处理之后再到reducer里面去
中间件实现的原理
就是对 store,dispacth 进行重写
代码如下:
var next = store.dispacth()
对store 进行重写
store.dispacth= (action)=>{
默认接收一个 action 对象
console.log("操作之前的数据",store.getState());
next(action);
console.log("操作之后的数据",store.getState())
}
- 使用第三方提供的redux-logger 中间件
作用主要是在 控制台 日志输出的中间件
- 安装 yarn add redux-logger --save 或 npm i --save redux-logger
在主仓库中引入: - import logger from 'redux-logger'
在主仓库的createStore(),传递 redux 的 applyMiddleware 调用即可
applyMiddleware 主要作用就是使用中间件,这个函数用中间件作为参数比如: logger thunk saga 一般的话, logger需要放在后面
代码如下:
import { createStore, applyMiddleware, compose } from "redux";
import reducer from "./reducer";
import logger from "redux-logger";
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducer, composeEnhancers(applyMiddleware(logger)));
export default store;
- 使用第三方提供的redux-thunk中间件(让Redux能够实现异步的代码)
- 安装 yarn add redux-thunk --save
- 默认store.dispacth()只能接受一个对象,如果使用了redux-thunk这个中间件 store.dispacth()能接受一个函数
- 简单demo如下写在组件里面
派发一个异步动作
store.dispatch(() => {
这里写一个异步的代码
var url = "http://localhost:9090/shuju";
fetch(url)
.then(response => response.json())
.then(res => {
再派发一个普通的动作
store.dispatch(initlist(res));
});
});
- 需要将这个方法放在 actionCreate.js 里面
因为在组件页面中 使用 store.dispacth() 这个方法使用了thunk 之后,里面可以接受一个函数或者是对象,在这个store.dispacth()参数的函数 放到actionCreate.js 里面自定义各一个函数里面可以发起ajax网络请求 actionCreate里面的函数经过第三方中间件的处理主动接受的参数有 store里面的 dispacth,getState 这两个方法,这样就不需要在重新的引入 store了 可以直接在 dispacth()一个动作给reducer.js
第一种方式组件里面的代码:
直接派发一个动作,但是这个动作是在actionCreate里面写
使用方式1 store.dispatch(initTodoSync); 注意不能加括号 , thunk 会让initTodoSync执行
(加括号的话initTodoSync返回一个undefined 而 store.dispacth 不能接受一个undefined)
第一种方式actionCreate代码如下:
export const initlist = list => {
return {
type: INIT_LIST, // 主的reducer文件中根据这个动作的类型,把获取到的数据给store
list
};
};
export const initTodoSync = (dispatch, getState) => {
var url = "http://localhost:9090/shuju";
fetch(url)
.then(response => response.json())
.then(res => {
console.log(res, "获取成功了吗?");
console.log(getState());
dispatch(initlist(res)); // 调用重新初始化仓库数据的函数,把获取的数据传过去
});
};
第二种方式组件里面的代码:
store.dispatch(initTodoSync()); //加括号
第二种方式actionCreate代码如下:
export const initlist = list => {
return {
type: INIT_LIST,
list
};
};
export const initTodoSync = () => {
return (dispatch, getState) => {
var url = "http://localhost:9090/shuju";
fetch(url)
.then(response => response.json())
.then(res => {
console.log(res, "获取成功了吗?");
console.log(getState());
dispatch(initlist(res));
});
};
};
redux-thunk 实现的原理:
var next = store.dispacth()
store.dispacth=(action)=>{
if(action && typeof action=== "function"){
//动作是个函数,就会直接执行这个动作,并且把两个参数传递下去
action(state.getState,state.dispacth)
} else{
next(action)
}
}
redux-react
安装: npm install react-redux || yarn add react-redux
UI组件与容器组件的概念
UI组件: 只是负责数据的渲染,不负责数据的操作. 不负责跟仓库打交道,所有的数据都是通过props
容器组件: 不负责数据渲染, 负责数据的操作, 跟仓库打交道 ,所有的数据都是通过仓库
connect的详解
connect 方法返回一个高阶函数,接收一个组件的参数,生成一个新的组件
connect 方法接收两个参数 第一个参数mapStateToprops (仓库数据发生改变时,自动执行,通过props属性自动给到组件页面) 第二个参数mapDispacthToProps
代码简单实现如下
import React, { Component } from "react";
import { connect } from "react-redux";
class Dashboard extends Component {
state = {
name: ""
};
render() {
const { name } = this.props;
return (
<div>
<h2>我的名字{name}</h2>
<button onClick={onTodoClick}>修改我的名字</button>
</div>
);
}
}
const mapStateToprops = state => {
return {
name: this.state.name
};
};
const mapDispacthToprops = () => {
return {
onTodoClick: () => {
dispatch({
type: "SET_VISIBILITY_FILTER",
name: this.state.name
});
}
};
};
export default connect(
mapStateToprops,
mapDispacthToprops
)(Dashboard);