美文网首页
React Demo解析(18/9/16更新)

React Demo解析(18/9/16更新)

作者: 李逍遥JK | 来源:发表于2018-09-16 23:11 被阅读84次

    周三到今天周日,连续看了几天的Dva。由于没怎么学ES6吃了,看的比较慢。今天终于有点眉目。于是记录一下

    项目结构

    image.png

    1.Component: Users

    import React from 'react';
    import { connect } from 'dva';
    import { Table, Pagination, Popconfirm, Button } from 'antd';
    import { routerRedux } from 'dva/router';
    import styles from './Users.css';
    import { PAGE_SIZE } from '../../constants';
    import UserModal from './UserModal';
    
    // React 对象 View ../component/Users/users
    function Users({ dispatch, list: dataSource, loading, total, page: current }) {
      function deleteHandler(id) {
        dispatch({
          type: 'users/remove',
          payload: id,
        });
      }
    
      function pageChangeHandler(page) {
        dispatch(routerRedux.push({
          pathname: '/users',
          query: { page },
        }));
      }
    
      function editHandler(id, values) {
        dispatch({
          type: 'users/patch',
          payload: { id, values },
        });
      }
      function createHandler(values) {
        dispatch({
          // 这里的users是model的命名空间,
          // "/"后面的表示model中effect的异步方法名
          type: 'users/create',
          // 这个表示要传递参数,当然这里可以是一个方法,作为回调方法
          // 传递到 service/user.js *cereate方法的第一个参数
          payload: values,
        });
      }
    
      const columns = [
        {
          title: 'Name',
          dataIndex: 'name',
          key: 'name',
          render: text => <a href="">{text}</a>,
        },
        {
          title: 'Email',
          dataIndex: 'email',
          key: 'email',
        },
        {
          title: 'Website',
          dataIndex: 'website',
          key: 'website',
        },
        {
          title: 'Operation',
          key: 'operation',
          // 每个操作单独渲染 ,并且获取唯一的user id
          /* bind 第一个参数 this 但是此处传null */
          render: (text, record) => (
            <span className={styles.operation}>
              <UserModal record={record} onOk={editHandler.bind(null, record.id)}>
                <a>Edit</a>
              </UserModal>
              <Popconfirm title="Confirm to delete?" onConfirm={deleteHandler.bind(null, record.id)}>
                <a href="">Delete</a>
              </Popconfirm>
            </span>
          ),
        },
      ];
    
      return (
        <div className={styles.normal}>
          <div>
            <div className={styles.create}>
              <UserModal record={{}} onOk={createHandler}>
                <Button type="primary">Create User</Button>
              </UserModal>
            </div>
            <Table
              columns={columns}
              dataSource={dataSource}
              loading={loading}
              rowKey={record => record.id}
              pagination={false}
            />
            <Pagination
              className="ant-table-pagination"
              total={total}
              current={current}
              pageSize={PAGE_SIZE}
              onChange={pageChangeHandler}
            />
          </div>
        </div>
      );
    }
    
    // connect 方法传入的第一个参数是 mapStateToProps 函数,
    // mapStateToProps 函数会返回一个对象,用于建立 State 到 Props 的映射关系
    // 通过这种方式来把model层的数据传递到当前组件
    function mapStateToProps(state) {
      const { list, total, page } = state.users;
    
      // 返回待遇loading, list, total, page的属性
      return {
        loading: state.loading.models.users,
        list,
        total,
        page,
      };
    }
    
    export default connect(mapStateToProps)(Users);
    

    2.Model: Users

    import * as usersService from '../services/users';
    // dva 提供 app.model 这个对象
    export default {
      namespace: 'users',
    
      state: {
        list: [],
        total: null,
        page: null,
      },
      // 这里的state是当前总的state,这里的{ payload: { data: list, total, page } }包含了下面传递的参数和type
      reducers: {
        save(state, { payload: { data: list, total, page } }) {
          // 这里用ES6语法来更新当前state中num的值。state 更新后 通过connect函数跟新Component中的值
          return { ...state, list, total, page };
        },
      },
      effects: {
        *fetch({ payload: { page = 1 } }, { call, put }) {
          const { data, headers } = yield call(usersService.fetch, { page });
          yield put({
            // 这里的put表示存储在当前命名空间users中,通过save方法存在当前state中
            // 调用reducers 中的save方法
            type: 'save',
            payload: {
              data,
              total: parseInt(headers['x-total-count'], 10),
              page: parseInt(page, 10),
            },
          });
        },
        // 遍历器函数(Generator)
        // { payload: id } 是从组件Users/Users传递过来的参数,这里就是上面定义的
        // 这里的call方法可以使用param参数传递给后台程序进行处理这里,也可以调用service层的方法进行调用后端程序,
        // 这里的put表示存储在当前命名空间users中,通过*reload方法存在当前state中
        // 在这里可以用ajax调用后台程序处理并返回数据,有很多种处理方式,当然有些处理不需要后端的,可以直接put方法更新state数据
        *remove({ payload: id }, { call, put }) {
          yield call(usersService.remove, id);
          yield put({ type: 'reload' });
        },
        *patch({ payload: { id, values } }, { call, put }) {
          yield call(usersService.patch, id, values);
          yield put({ type: 'reload' });
        },
        *create({ payload: values }, { call, put }) {
          yield call(usersService.create, values);
          yield put({ type: 'reload' });
        },
        *reload(action, { put, select }) {
          const page = yield select(state => state.users.page);
          yield put({ type: 'fetch', payload: { page } });
        },
      },
      subscriptions: {
        setup({ dispatch, history }) {
          return history.listen(({ pathname, query }) => {
            if (pathname === '/users') {
              dispatch({ type: 'fetch', payload: query });
            }
          });
        },
      },
    };
    

    相关文章

      网友评论

          本文标题:React Demo解析(18/9/16更新)

          本文链接:https://www.haomeiwen.com/subject/llrppftx.html