react从入门到放弃 之 redux
react从入门到放弃 之 redux
激进黄瓜酱 发表于2年前
react从入门到放弃 之 redux
  • 发表于 2年前
  • 阅读 127
  • 收藏 1
  • 点赞 0
  • 评论 0

新睿云服务器60天免费使用,快来体验!>>>   

摘要: redux的同步 异步 中间件

redux 是干嘛的?

因为react项目视图嵌套,有时候嵌套太深,那么数据的管理就会非常复杂。 redux是一套非常有效的 用于集中管理你认为应该被他管理的组件的state的集中地。 redux可以用简单的代码 在任何组件直接拿到redux管理的数据 并且进行操作(action)

一些废话

本文是个人学习的笔记 使用概念上的一些看法 并不是标准的教条、教程,放在网上仅供各位交流参考 redux中文文档地址

demo

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' // 打印 action
import { 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 容器组件 如何使用redux
import { 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 }
}
  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 2
博文 11
码字总数 5088
×
激进黄瓜酱
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: