之前用react的做的項目一直都是用class ,setState,componentDidMount ,componentDidUpdate ,componentWillUnmount 的寫法,但從16.8以來,react新增了Hook特性,對于喜歡技術嘗試我的來說,豈能不試一下新寫法。
我們一般用react 的ant-design架構做背景管理系統,那麼最常見的業務場景就是表格,查詢,分頁。下面我就拿最常用的一個例子和大家分享一下:
首先請看我們的界面:
上面是搜尋條件,中間是表格,下面是分頁。這個大家一眼就能看懂,那麼我就來給大家上代碼
//注意這個js代碼整個對應上面的UI展示,是我們項目裡的一個頁面,裡面部分字段可能大家可能用不上。
import React, { useCallback, useEffect, useState} from 'react';
import {Collapse, Table, Button, Space, Form, Input, Select, DatePicker,} from 'antd';
//注意此處是我們請求接口後傳回的資料,這裡我是把所有的api請求都提出來了,下面filterUser和getList就是我們這個頁面需要用到的api
import {filterUser, getList} from "../../service/user";
//moment是為了時間選擇器,選擇後進行時間格式化所用
import moment from 'moment';
import 'moment/locale/zh-cn';
//locale是為了中文化時間控件的,如果其他的控件是非中文的,也可以按照這個寫法中文化
import locale from 'antd/es/locale/zh_CN';
//引入本頁面的樣式檔案
import "./list.css";
const {Panel} = Collapse;
const {Option} = Select;
const {RangePicker} = DatePicker;
function List() {
//設定頁碼
let [page,setPage] = useState(1);
//設定每頁條數
let size = 2;
//設定總頁數
const [total,setTotal] = useState(0);
//搜尋條件
let filter = {
mobile:'',
nickname:'',
channel_id:0,
tag_key:'',
min_create_time:0,
max_create_time:0,
};
//請求資料時loading狀态
const [load,setLoad] = useState(false);
//表格資料
const [tableData,setTableData] = useState([]);
//此處是為了初始化時候請求一次資料
useEffect(()=>{
pageChange(page,size);
},[])
//點選下面的分頁按鈕觸發的方法
const pageChange = useCallback(
(currentPage,currentSize)=>{
// debugger
console.log(currentPage,currentSize,"1")
page = currentPage === undefined ? page : currentPage;
setPage(page);
size = currentSize === undefined ? size : currentSize;
fetchData();
},
[]
)
//點選搜尋按鈕觸發的方法
const searchData = useCallback(
(values)=>{
// debugger
console.log(values)
filter.mobile = values && values.mobile !== undefined ? values.mobile : '';
filter.nickname = values && values.nickname !== undefined ? values.nickname : '';
filter.channel_id = values && values.channel_id !== undefined ? values.channel_id : 0;
filter.tag_key = values && values.tag_key !== undefined ? values.tag_key : '';
if(values && values.create_time !== undefined){
let min_create_time = parseInt(moment(values.create_time[0]).valueOf()/1000);
let max_create_time = parseInt(moment(values.create_time[1]).valueOf()/1000);
filter.min_create_time = min_create_time;
filter.max_create_time = max_create_time;
}else{
filter.min_create_time = 0;
filter.max_create_time = 0;
}
page = 1;
setPage(page);
console.log("search",page,size)
console.log("search filter",filter)
fetchData();
},[]
)
//Api請求背景接口的方法
const fetchData = async()=> {
setLoad(true);
let params = {page, size, ...filter};
let result = await getList(params);
setLoad(false);
if (result.code === 0) {
result = result.data;
console.log("result", result);
let table = [...result.list];
setTotal(result.total_size);
setTableData([...table]);
console.log("table", table)
}
}
//表頭列
const columns = [
{
title: '使用者ID',
dataIndex: 'id',
},
{
title: '昵稱',
dataIndex: 'nickname',
},
{
title: '手機号',
dataIndex: 'mobile',
},
{
title: '來源管道',
dataIndex: 'reg_channel_desc',
},
{
title: '注冊時間',
dataIndex: 'create_time_desc',
},
];
//擷取搜尋條件的api
const [user_channel,setUser_channel] = useState([]);
const [user_tag,setUser_tag] = useState([]);
useEffect(()=>{
let params = {
show_user_tag:true,
show_user_channel:true,
show_user_identifier:true,
};
const fetchData = async ()=>{
const result = await filterUser(params);
if(result.code === 0){
const userChannel = result.data&&result.data.user_channel ? result.data.user_channel : [];
const userTag = result.data&&result.data.user_tag ? result.data.user_tag : [];
setUser_channel(userChannel);
setUser_tag(userTag);
}
}
fetchData();
},[])
//重置表單
const [form] = Form.useForm();
const reset = ()=>{
form.resetFields();
//此處尤其要注意,resetFields表單重置後會重新mount元件,是以不必在這裡重新調用請求api的接口。
//重置之後,會自動調用搜尋清單的方法。
}
return (
<div>
<h1>使用者清單</h1>
<Collapse defaultActiveKey={['1']} style={{marginBottom:'20px'}}>
<Panel header="搜尋條件" key="1">
<Form className="list"
autoComplete="off"
layout="inline"
name="basic"
form={form}
initialValues={{remember: true}}
onFinish={searchData}
>
<Form.Item
label="手機号"
name="mobile"
>
<Input allowClear/>
</Form.Item>
<Form.Item
label="昵稱"
name="nickname"
>
<Input allowClear/>
</Form.Item>
<Form.Item
label="使用者标簽"
name="tag_key"
>
<Select
showSearch allowClear
style={{width: 200}}
placeholder="選擇使用者标簽"
optionFilterProp="children"
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
{
user_tag.map((item, i) => {
return (
<Option value={item.key} key={item.key}>{item.val}</Option>
)
})
}
</Select>
</Form.Item>
<Form.Item
label="來源管道"
name="channel_id"
>
<Select
showSearch allowClear
style={{width: 200}}
placeholder="選擇來源管道"
optionFilterProp="children"
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
{
user_channel.map((item, i) => {
return (
<Option value={item.key} key={item.key}>{item.val}</Option>
)
})
}
</Select>
</Form.Item>
<Form.Item
label="注冊時間"
name="create_time"
>
<RangePicker locale={locale}/>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
查詢
</Button>
<Button htmlType="submit" className="reset" onClick={reset}>
重置
</Button>
</Form.Item>
</Form>
</Panel>
</Collapse>
<Table rowKey="id" columns={columns} loading={load}
dataSource={tableData} bordered
scroll={{y: 500}}
rowSelection={{selectedRowKeys: []}}
pagination={{showSizeChanger:true,onChange:pageChange,
pageSizeOptions:['2','5','10'],defaultPageSize:size,
showTotal: ()=>{return `共${total}條資料`},
current:page,total:total}}
/>
</div>
);
}
export default List;
既然大家使用hook寫東西了,那麼關于hook的一些知識肯定也有一些了解,很多文章和部落格也有介紹,這裡我就不多說了,下面為大家附上官網位址:react hook官網位址
這是我在項目裡能想到的一個寫法,如果大家有更好的寫法,歡迎和我分享。非常樂意和大家一起學習,一起進步。