redux 是干嘛的?因为react项目视图嵌套,有时候嵌套太深,那么数据的管理就会非常复杂。redux是一套非常有效的 用于集中管理你认为应该被他管理的组件的state的集中地。redux可以用简单
redux 是干嘛的?
因为react项目视图嵌套,有时候嵌套太深,那么数据的管理就会非常复杂。redux是一套非常有效的 用于集中管理你认为应该被他管理的组件的state的集中地。redux可以用简单的代码 在任何组件直接拿到redux管理的数据 并且进行操作(action)
一些废话
本文是个人学习的笔记 使用概念上的一些看法 并不是标准的教条、教程,放在网上仅供各位交流参考redux中文文档地址
demo
git 地址: https://git.oschina.net/huanggua/react-redux-demo.git
安装:npm install运行:npm run dev
环境
"redux": "^3.5.2" //redux 本体"react-redux": "^4.4.5" // 结合react的"redux-logger": "^2.6.1" //打印action"redux-thunk": "^2.1.0" //redux 异步"isomorphic-fetch": "^2.2.1" //进行网络请求的 也可以用jq的ajax 随意
redux一些概念
- action: 描述请求的 发送一个请求 去修改redux管理的state 从而达到数据控制组件的功能
- reducer:根据action类型 传入的参数 进行分流 对 redux的state(store)增删改
redux 同步数据 具体代码
运行顺序 jsx组件 调用 action 传到 reducer 修改数据 重新渲染组件
==========index or main 、 app 入口文件配置===============
//index or main 、 app 入口文件配置import { createStore, applyMiddleware } from 'redux'; // 创建 redux的store 和 配置 中间件import thunk from 'redux-thunk'; // 中间件 用于 异步加载import createLogger from 'redux-logger' // 打印 actionimport { Provider } from 'react-redux';import reducer from './reducers/reducer.js';const loggerMiddleware = createLogger()let store = createStore( // 坑:这里的参数一定要注意顺序 reducer, // 你的reducer 文件 window.devToolsExtension && window.devToolsExtension(), //redux 浏览器插件 在Chrome 浏览器 搜索 redux 插件 安装 applyMiddleware( //配置redux中间件 thunk, //允许action 返回function 并运行function function内可以调用dispatch 用于异步加载 链接服务器用 loggerMiddleware //在控制台打印 action ))ReactDOM.render( <Provider store={store}> <MyRouter/> </Provider> , document.getElementById('root'));
=============action的配置========================
//action的配置//定义action的类型/** 电影页面 数据操作*/export const MOVIE_INIT = 'MOVIE_INIT'; //初始化电影export const MOVIE_ADD = 'MOVIE_ADD_MOVIE'; //新增电影export const MOVIE_UPDATA = 'MOVIE_UPDATA'; //修改电影export const MOVIE_REMO = 'MOVIE_REMO'; //删除电影//定义action方法 定义传入的变量 最终返回 action的type 和 调用action时传入的变量export function initMovie(initData) { return { type: MOVIE_INIT, initData }}//新增电影export function addMovie(form) { return { type: MOVIE_ADD, form }}//修改电影export function updataMovie(form) { return { type: MOVIE_UPDATA, form }}.........
===============reducer 的配置=======================
//reducer 的配置import { combineReducers } from 'redux'import { MOVIE_ADD, MOVIE_UPDATA, MOVIE_REMO, MOVIE_INIT , MOVIE_LOAD} from '../actions/actions.js' //action类型import * as doMovieData from '../dataCentre/movies/movieData.js'; //自定义的 处理数据的文件// 电影页面 处理数据 state参数就是 movieData 指向的数据 action里包含了传进来的数据function movieData(state = {load:false}, action) { switch (action.type) { case MOVIE_INIT: //这里有个大坑:return的 是一个新的state对象 不要在原有对象基础上 进行修改 要全新的 return doMovieData.data_init(state, action); case MOVIE_ADD: return doMovieData.data_add(state, action); case MOVIE_UPDATA: return doMovieData.data_updata(state, action); case MOVIE_REMO: return doMovieData.data_remo(state, action); case MOVIE_LOAD: return doMovieData.data_load(state, action); default: return state }}//可以写多个function 我建议根据路由 每个页面写一个function 一个function管理一个页面// 注意 如果多个function action的type写的一样的话 两个function 相同的case 都会执行的const reducer = combineReducers({ movieData //多个function 可以在这里继续})export default reducer
==============jsx 容器组件 如何使用redux===================
//jsx 容器组件 如何使用reduximport { connect } from 'react-redux'import * as movieAction from '../../actions/actions.js'class MovieIndex extends Component {........ //1.初始化数据 2.页面切换 刷新数据 componentWillMount(){ let { dispatch } = this.props; dispatch(movieAction.getInitData()); } render() { <MovieTable data={this.props.movieData.data} /> }.....function select(state) { return { movieData: state.movieData //这里的state 就是 redux 管理的 数据state movieData 就是reducer的一个function };}export default connect(select)(MovieIndex); //jsx组件交给 redux处理 把 redux的东西注入}
组件通过注入的dispatch 调用action action里有传入的参数 与类型reducer根据action去改变state 但是 这样只是同步数据我也不懂什么是同步数据 但是我发现我在reducer 如果使用ajax的话 方法是不等ajax的请求延迟的 会直接跳过ajax 等ajax执行了 拿到数据 return redux的数据也不会变更 所以我们要用异步加载了!
redux 异步数据
我们之前已经 在入口文件处 配置过异步加载需要的东西了 写法上有变化的 只有action文件了 或者就是action的写法 我们可以在action里调用dispatch 哈哈你只需要 在action 返回一个函数 return (dispatch, getState)=> {}
//初始化电影export function getInitData(initData) { return (dispatch, getState) => { //应用场景:我们需要请求数据的时候 我们要先通知 组件进入加载了 改变redux控制加载的组件显示 请求拿到数据之后 通知加载关闭 并把数据合并到redux//fetch 是新的 网络请求的api 使用要 import fetch from 'isomorphic-fetch'; //首先让load组件 显示 dispatch(updataLoad()); setTimeout(function () { //预设个定时器 模拟网络延迟 fetch('./test.json') .then( function (response) { if (response.status !== 200) { console.log('当前状态码为: ' + response.status); return null; //测试不存在这种情况 先不管 } response.json().then(function (data) { // 把数据存入 state //成功之后 load不显示 dispatch(initMovie(data)); dispatch(updataLoad()); }); } ) .catch(function (err) { console.log('Fetch Error :-S', err); }); }, 2000) } // return { type: MOVIE_INIT, initData }}