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

腾讯云 技术升级10大核心产品年终让利>>>   

摘要: 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 }
}
共有 人打赏支持
粉丝 3
博文 11
码字总数 5088
×
激进黄瓜酱
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: