美文网首页
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