ant design pro用法學習

前端採用螞蟻金服的前端集成框架:ant-design-pro, 官網:https://pro.ant.design/

前端採用ant-design,其中是用react寫的,所以針對後端開發人員而言,學習也不是那麼快,該文章用於能夠快速的讓後端人員上手。

一、主要文件

這裏主要介紹,平常開發中可能用到的一些文件,這裏分爲兩類:

配置文件
界面文件

1.配置文件

該文件用於非界面文件,用於項目中的配置的介紹

  1. 後端配置文件

  2. 菜單中文設置文件

  3. 菜單層級設置文件

1.後端配置文件

這裏在當前的ant-design版本中文件爲

/src/config.js

// 其中最重要的是這裏
proxy: {
    // 下面是在遇到這種路徑的時候進行替換
  '/like/tina/api/v1/': {
    // 自己的路徑,其中8084是後端的端口號
    target: 'http://localhost:8084/like/tina/api/v1/',
    changeOrigin: true,
    pathRewrite: { '^/like/tina/api/v1': '' },
  },
},

其中該配置文件主要用於 xxxxApi.js 文件針對後端的url的替換

注意:這裏面最後請求的路徑會自動修改掉,但是在瀏覽器下面查看的ip是不會變的,參考(這裏),但是實際的鏈接已經被代理成,而且能夠獲取數據,請注意

在console中展示的可能還是Http://localhost:8000/xxxxx,但是實際上已經替換爲我們自己的這個了,比如:http://localhost:8080/like/tina/api/v1//user/table

2.菜單中文設置文件

文件爲(其中我們只考慮中文的轉換,其他的暫時不考慮):

/src/locales/zh-CN/menu.js

文件介紹,該文件主要是給左側菜單中的中文展示使用

export default {
  'menu.home': '首頁',
  'menu.dashboard': 'Dashboard',
  'menu.dashboard.analysis': '分析頁',
  'menu.dashboard.monitor': '監控頁',
  'menu.dashboard.workplace': '工作臺',
  'menu.form': '表單頁',
  'menu.form.basicform': '基礎表單',
  'menu.form.stepform': '分步表單',
  'menu.form.stepform.info': '分步表單(填寫轉賬信息)',
  'menu.form.stepform.confirm': '分步表單(確認轉賬信息)',
  'menu.form.stepform.result': '分步表單(完成)',
  'menu.form.advancedform': '高級表單',
  'menu.list': '列表頁',
  'menu.list.searchtable': '查詢表格',
  'menu.list.basiclist': '標準列表',
  'menu.list.cardlist': '卡片列表',
  'menu.list.searchlist': '搜索列表',
  'menu.list.searchlist.articles': '搜索列表(文章)',
  'menu.list.searchlist.projects': '搜索列表(項目)',
  'menu.list.searchlist.applications': '搜索列表(應用)',
  'menu.config': '配置',
  'menu.config.configgrouplist': '配置組',
  'menu.config.configitemlist': '配置項',
  'menu.profile': '詳情頁',
  'menu.profile.basic': '基礎詳情頁',
  'menu.profile.advanced': '高級詳情頁',
  'menu.result': '結果頁',
  'menu.result.success': '成功頁',
  'menu.result.fail': '失敗頁',
  'menu.exception': '異常頁',
  'menu.exception.not-permission': '403',
  'menu.exception.not-find': '404',
  'menu.exception.server-error': '500',
  'menu.exception.trigger': '觸發錯誤',
  'menu.account': '個人頁',
  'menu.account.center': '個人中心',
  'menu.account.settings': '個人設置',
  'menu.account.trigger': '觸發報錯',
  'menu.account.logout': '退出登錄',
  'menu.task': '調度',
  'menu.task.tasklist': '任務調度',
};

比如其中的一條數據:menu.task.tasklist:‘任務調度’,該條數據用於在菜單層級設置中,比如如下,其中就是在界面展示的

export default [
  ...
      {
        path: '/task',
        icon: 'project',
        name: 'task',
        routes: [
          {
            path: '/task/task-list',
            // 這裏就是跟中文對應的文件名
            name: 'tasklist',
            component: './like/TaskList',
          },
        ],
      },
  ...
];

3.菜單層級設置文件

文件爲:

/config/router.config.js

該文件用於顯示菜單,還是比較重要的,但是要展示自己的菜單的話,還是要自己進行單獨設置,不過一鍵式工具中我們已經可以直接生成了,下面主要針對文件進行介紹下,全量文件如下

export default [
  // user
  {
    path: '/user',
    component: '../layouts/UserLayout',
    routes: [
      { path: '/user', redirect: '/user/login' },
      { path: '/user/login', component: './User/Login' },
      { path: '/user/register', component: './User/Register' },
      { path: '/user/register-result', component: './User/RegisterResult' },
    ],
  },
  // app
  {
    path: '/',
    component: '../layouts/BasicLayout',
    Routes: ['src/pages/Authorized'],
    authority: ['admin', 'user'],
    routes: [
      // dashboard
      { path: '/', redirect: '/dashboard/analysis' },
      {
        path: '/config',
        icon: 'setting',
        name: 'config',
        routes: [
          {
            path: '/config/config-group-list',
            name: 'configgrouplist',
            component: './config/ConfigGroupList',
          },
          {
            path: '/config/config-item-list',
            name: 'configitemlist',
            component: './config/ConfigItemList',
          },
        ],
      },
      {
        path: '/task',
        icon: 'project',
        name: 'task',
        routes: [
          {
            path: '/task/task-list',
            name: 'tasklist',
            component: './like/TaskList',
          },
        ],
      },
      {
        component: '404',
      },
    ],
  },
];

其中如果有routes則就表示是父級菜單,可以進行測試下,其中內部的爲子菜單,而子菜單還是可以繼續向下拆分,其中component就是指向我們自己的component,就是界面xxxList.js文件

2.界面文件

1.界面展示文件(默認用List結尾)

自動生成工具會直接生成對應的表名+List.js,該文件就是直接在界面上展示的文件,下面主要介紹下這文件的結構

import React, { PureComponent } from 'react';
import { connect } from 'dva';
 
// 引入antdesign的組件
import {
  Row,
  Col,
  Card,
  Badge,
  Form,
  Input,
  Button,
  Table,
  Icon,
  Select,
  Divider,
  Drawer,
  Pagination,
  InputNumber,
  Tabs,
  Modal,
} from 'antd';
 
 
// 引用第三方文件
import 'codemirror/theme/solarized.css';
 
// 下面@connect 這個是將Model文件中的數據和當前界面List關聯起來
/* eslint react/no-multi-comp:0 */
@connect(({ taskModel, loading }) => ({
  // 這裏是Model文件的namespace(注意:一定要保持一致)
  taskModel,
  loading: loading.models.taskModel,
}))
// @Form.create() 是一個註解,就簡化了xxx = Form.create(xxx);export xxx
@Form.create()
class TaskList extends PureComponent {
  // 這個是List的一些數據,也可以放到Model中
  state = {
    addModalVisible: false,
    editModalVisible: false,
    item: {},
  };
 
  // 界面展示的列
  columns = [
    {
      name: 'id',
      title: 'index',
      dataIndex: 'id',
      width: '8%',
    },
  ];
 
  // 界面初始化
  componentDidMount() {
    ...
  }
 
  // 普通的函數
  onClose = () => {
    // 重要:當我們要調用Model中的函數的時候,應該通過dispatch來調用
    const { dispatch } = this.props;
 
    // 其中
    dispatch({
      type: 'configItem/getListCount',
      payload: {
        paneIndex: index,
        searchParam: param,
      },
    });
  };
 
  // 界面加載,每次數據有更新,該函數都會執行
  render() {
    // 變量引用:props方式,props是外部數據引用過來的變量,比如Model文件,我們這裏引入,Model中的數據就應該這樣使用
    const {
      taskModel: { selectState, groupAllCodeList, drawerRecord, resultOfRun, drawerVisible },
    } = this.props;
 
    // 變量引用:state方式,這個其中的變量都是自己內部的
    const { addModalVisible, editModalVisible, item } = this.state;
 
    // 定義的一些定量
    const components = {
      body: {
        row: EditableFormRow,
        cell: EditableCell,
      },
    };
 
    // 封裝的表格
    const tabPanes = panes.map(pane => (
      <Tabs.TabPane tab={pane.title} key={pane.name}>
        <Card bordered={false}>
          <div className={styles.tableList}>
            {/*這裏是搜索框部分*/}
            <div className={styles.tableListForm}>{this.renderSearchForm()}</div>
            <div className={styles.tableListOperator} />
 
            {/*這是表格*/}
            <Table
              rowKey={record => record.id}
              dataSource={pane.content.tableList}
              columns={this.columns}
              loading={pane.content.tableLoading}
              pagination={false}
              expandedRowRender={this.expandedRowRender}
            />
            
            {/*這裏是頁面分頁部分*/}
            <Pagination
              showQuickJumper
              onChange={this.onChange}
              defaultCurrent={1}
              total={pane.content.totalNumber}
              current={pane.content.pager.pageNo}
              defaultPageSize={pane.content.pager.pageSize}
            />
          </div>
        </Card>
      </Tabs.TabPane>
    ));
 
    // 這裏返回界面元素
    return (
      // 該標籤爲antdesign的的標籤,用於菜單和界面顯示
      <PageHeaderWrapper>
        <Tabs
          onChange={this.onTabChange}
          activeKey={activePaneName}
          defaultActiveKey="1"
          type="editable-card"
          onEdit={this.onEdit}
        >
          {tabPanes}
        </Tabs>
      </PageHeaderWrapper>
    );
  }
}
 
export default TaskList;java

2.界面數據文件(默認用Model結尾)

// 引入Api文件
import {
  pageList,
  add,
  deleteData,
  update,
  pageCount,
  getCodeList,
  getAllCodeList,
  disable,
  enable,
  run,
  handRun,
} from '@/services/taskApi';
 
export default {
  namespace: 'taskModel', // 這個是標示當前model的,用於跟List文件關聯
 
  // 下面是定義的數據模型
  state: {
    maxTabIndex: 1, // 最大的標籤頁索引,用於標籤新增計數用
    activePaneName: '1', // tabPane 的激活的key
    tabIndexList: ['1'], // 當前存在的標籤的列表
    panes: [
      {
        name: '1',
        title: '任務調度1',
        content: {
          tableList: [],
          tableLoading: false,
          searchParam: {},
          totalNumber: 0,
          pager: {
            pageNo: 1,
            pageSize: 20,
          },
        },
      },
    ],
  },
 
  // 異步處理函數
  effects: {
 
    // 增加組配置,payload爲List調度過來的參數,call爲調用Api函數的方法,put爲調用其他異步或者同步的方法
    *add({ payload }, { call, put }) {
      console.log('task.add 參數:');
      // 打印複雜函數
      console.log(JSON.stringify(payload));
 
      // 調用Api文件中的某個函數add,這裏
      const response = yield call(add, payload);
      yield put({
        type: 'handleAddResult',
        payload: response,
      });
 
      // 調用其他的函數,同步或者異步函數均可
      yield put({
        type: 'tableFresh',
        payload: {
          paneIndex: payload.paneIndex,
        },
      });
    },
 
    // 其他函數
    ...
  },
 
  // 同步函數
  reducers: {
     
    // 同步函數xxx
    setTableLoading(state) {
      const newPanes = state.panes;
      const index = newPanes.findIndex(pane => pane.name === state.activePaneName);
      newPanes[index].content.tableLoading = true;
 
      // 下面這個retuen 在同步函數中必須存在
      return {
        ...state, // 這裏...是不修改除了下面這個panes之外的其他數據,注意:...state必須有,否則其他的數據都會被清空
        panes: newPanes, // 這裏是更新state中的panes字段
      };
    },
     
    // 其他函數
    ...
 
  },
};

3.跟後端交互文件(默認用Api結尾)

該文件是跟後端發送url的地方

import request from '@/utils/request';
 
// 這裏我用一個變量統一表示,這個正好可以給config.js文件中的代理進行替換
const path = '/like/tina/api/v1';
 
export async function add(params) {
  console.log('taskApi.add 發送的參數');
  console.log(JSON.stringify(params));
   
  // request是框架封裝的函數,body爲對應的參數,method不填寫,則默認爲GET
  return request(`${path}/task/add`, {
    method: 'PUT',
    body: {
      ...params,
    },
  });
}
 
export async function deleteData(params) {
  console.log('taskApi.deleteData 發送的參數');
  console.log(JSON.stringify(params));
  return request(`${path}/task/delete/${params}`, {
    method: 'DELETE',
  });
}
 
//
export async function getCodeList() {
  console.log('taskApi.getCodeList 發送');
  return request(`${path}/task/codeList`);
}
 
 
export async function update(params) {
  console.log('taskApi.update 發送的參數');
  console.log(JSON.stringify(params));
  return request(`${path}/task/update`, {
    method: 'POST',
    body: {
      ...params,
    },
  });
}

二、頁面加載流程

整體的流程是這樣的:

List->Model→Api——>後端

其中Model中放置的是數據,發起方是List模塊的dispatch,一旦數據獲取到更新到Model中,List界面會自動刷新,整體的流程圖是這樣的解釋:

connect :對應@connect這個註解
dispatch:對應的是dispatch函數
action:新的版本中已經將action這個模塊刪除掉了,早期的寫法中是還有一層Action,List那邊dispatch的其實是Action這一層中的函數,而這一層再調用Model,現在新的版本中已經直接採用dispatch調用Model中的函數了,Action層已經嵌入到內核中
Model:對應的就是我們的Model文件
Effect:這個是Model中的異步函數,用於界面中調用獲取數據比較耗時的操作,一般用於調用後端數據
Reducer:同步函數,用於界面中的數據,一般用於在界面處理後可以直接更新,並展示到界面中,是阻塞性函數
Subscriptioin:這個函數我們這邊用的不多,主要是一種訂閱,詳細可參考這裏:https://dvajs.com/guide/concepts.html#effect

Server:就是我們的後端

三、文件數據用法

其中主要介紹下List怎麼調用Model中的數據,其實在上面的List文件中已經介紹了,下面簡單介紹下

// 變量引用:props方式,props是外部數據引用過來的變量,比如Model文件,我們這裏引入,Model中的數據就應該這樣使用
const {
  taskModel: { selectState, groupAllCodeList, drawerRecord, resultOfRun, drawerVisible },
} = this.props;

要這樣寫纔行,引用某個變量的數據

四、注意事項(重要)

主要介紹一些語法糖,很多都是小細節,小坑,網上資料也較少,建議關注下

1.變量的…含義

// 同步函數xxx
setTableLoading(state) {
  const newPanes = state.panes;
  const index = newPanes.findIndex(pane => pane.name === state.activePaneName);
  newPanes[index].content.tableLoading = true;
 
  // 下面這個retuen 在同步函數中必須存在
  return {
    ...state, // 這裏...是不修改除了下面這個panes之外的其他數據,注意:...state必須有,否則其他的數據都會被清空
    panes: newPanes, // 這裏是更新state中的panes字段
  };
},

在代碼中經常會見到這種“…”三個點的變量,這種表示是將變量的key展示出來

比如如果一個類型是這種:tem:{“key1”:123,“key2”:222},這個變量爲tem,…tem 這個就表示:“key1”:123, “key2”:222,其實就是將外層剝離

2.變量,這種寫法

在代碼中有時候會見到這種寫法,如下

dispatch({
  type: 'configItem/getPageList',
  payload: {
    paneIndex: index,
    pager,   // 這裏其實就是pager:pager, 這個的簡化版,就是key和value的名字相同,就可以這樣寫,而且建議這樣寫,否則覈查會有告警
    searchParam: param,
  },
});

3.變量的打印

在日誌中打印平常都是使用console.log(xxxx) 即可,但是對於複雜類型,這個打印就顯示有點複雜,這裏建議使用JSON打印,如下這樣

console.log(JSON.stringify(item));

注意:
其中不能這麼寫,如下:

console.log("變量爲:"+JSON.stringify(item));

不能將JSON的解析和前面的字符鏈接,這樣後來發現,就是這個JSON不生效

4.函數的寫法

函數的寫法跟舊的js寫法不一樣,沒有function關鍵字,平常函數都這麼寫

// 沒有參數
renderSearchForm = () => {
   
};
 
// 一個參數
enable = record => {
   
};
 
// 多個參數
contain = (object1, object2) => {
   
};

5.列中屬性函數調用寫法

在column中可能會添加Button或者Icon等控件,進行函數的跳轉,在寫的時候一定要注意使用如下的方式

{
  key: 'delete',
  title: '刪除',
  dataIndex: 'delete',
  editable: false,
  width: '5%',
  render: (text, row) => (
    <span>
      <Button type="danger" icon="delete" onClick={() => this.showDeleteConfirm(row)} />
    </span>
  ),
},

注意:其中函數調用一定要寫成

onClick={() => this.fun()}

而不能寫成如下: 下面這個會自動調用函數fun()

onClick={this.fun()}

6.js文件中的註釋

其中"//"之後要添加一個空格,否則會報錯

7.List頁面調用

這個頁面可以調用異步也可以調用同步函數,但是異步一般用於獲取數據耗時比較長的,一般用於從後端獲取數據並覆蓋前端數據,同步函數用於直接將進行數據操作

8.Model頁面函數調用

Model頁面中有兩種函數,異步函數和同步函數,但是異步函數可以調用同步函數也可以調用異步函數,而同步函數不可以調用其他的函數。

五、參考

dva概念:https://dvajs.com/guide/concepts.html#effectreact語法:https://www.jianshu.com/p/7e872afeae42antdesign官網:https://pro.ant.design/docs/getting-started-cnantdesign組件庫:https://ant.design/docs/react/introduce-cnantdesign目錄解釋:https://pro.ant.design/docs/getting-started-cnhttp://www.cnblogs.com/bjlhx/p/8973658.htmlantdesignpro詳細介紹:https://www.ctolib.com/topics-134955.html

六、學習參考:

https://blog.csdn.net/luo1055120207/article/details/78953381https://blog.csdn.net/qietingfengdeyanse/article/details/81206292https://zhuanlan.zhihu.com/p/36134136https://pro.ant.design/index-cnhttp://www.cnblogs.com/bjlhx/p/9009056.htmlhttps://www.ru23.com/note/ab0115f0.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章