文章目錄
- 1、字段渲染
- 2、異步請求展示明細
- 3、hover展示問題
- 3.1 基本邏輯
- 3.2 hover時長判斷
- 3.3 render+hover
表格字段明細展示,屬于比較小的需求,但是也有一定交互細節,本文選取部分場景。
1、字段渲染
- render和渲染組件是有區別的。
- render常見為函數轉化,利用頁面和全局的變量state來渲染,最終返回Dom結構,偏向于展示和數據處理。函數參數和原來一致。
- 渲染組件提供了自己的狀態,有利于該字段的交互邏輯集中在組件中,盡量少利用外部變量。注意函數參數的變化,由props引入。
- 命名方式略有不同,函數駝峰即可,組件大寫字母開頭+駝峰。
import { Table } from "antd";
import React, { useState } from "react";const RenderNameCom = ({ text }) => {const [loading, setLoading] = useState(false);return (<divonClick={() => {setLoading(true);setTimeout(() => {setLoading(false);}, 2000);}}>{loading ? "Loading..." : text}</div>);
};const renderNameFun = (text) => {const textLast = text > 10 ? "..." : text;return <div>{textLast}</div>;
};export const columns = [{title: "Name",dataIndex: "name",render: (text) => <RenderNameCom text={text} />,},{title: "Age",dataIndex: "age",render: renderNameFun,},
];const testPage = () => {return (<Table columns={columns} dataSource={[{ name: "John Doe", age: 32 }]} />);
};export default testPage;
2、異步請求展示明細
- click點擊比較常見,單次點擊也比較保守和穩定,配合disabled(或者loading)保證同一時間不在接受觸發事件。
- 獲取展開狀態visible(新版本使用open屬性),可以進行靈活判斷,不再進行觸發請求。
- 如果沒有disabled禁用,連續點擊觸發多次,彈框
import { Table } from "antd";
import React, { useState } from "react";
import { Button, Popover, Spin, Divider } from "antd";const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));const RenderNameCom = ({ text }) => {const [show, setShow] = useState(false);const [loading, setLoading] = useState(false);const [data, setData] = useState({width: 0,height: 0,top: 0,left: 0,});const onClick = async () => {// 當未展開時,點擊可以發起請求;展開后,默認會關閉,阻止多余請求if (show) {return;}try {setLoading(true);await delay(2000);setData({width: 100,height: 100,top: 100,left: 100,});console.log("clicked");setLoading(false);} catch (error) {console.log(error);setLoading(false);}};return (<Popovercontent={loading ? (<Spin />) : (<div><p>Name: {text}</p><Divider /><p>Width: {data?.width}</p><p>Height: {data?.height}</p><p>Top: {data?.top}</p><p>Left: {data?.left}</p></div>)}trigger="click"visible={show}onVisibleChange={(visible) => setShow(visible)}><Button type="link" onClick={onClick} disabled={loading}>{text}</Button></Popover>);
};export const columns = [{title: "Name",dataIndex: "name",render: (text) => <RenderNameCom text={text} />,},
];const testPage = () => {return (<Table columns={columns} dataSource={[{ name: "John Doe", age: 32 }]} />);
};export default testPage;
3、hover展示問題
3.1 基本邏輯
- 用click的基礎代碼,改為hover觸發基本完成任務
- 問題在于hover存在鼠標滑過頻率很快的問題,誤觸發概率很大。
import { Table } from "antd";
import React, { useState } from "react";
import { Button, Popover, Spin, Divider } from "antd";const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));const RenderNameCom = ({ text }) => {const [show, setShow] = useState(false);const [loading, setLoading] = useState(false);const [data, setData] = useState({width: 0,height: 0,top: 0,left: 0,});const onClick = async () => {console.log("clicked start");if (show) {return;}try {setLoading(true);await delay(2000);setData({width: 100,height: 100,top: 100,left: 100,});console.log("clicked");setLoading(false);} catch (error) {console.log(error);setLoading(false);}};return (<Popovercontent={loading ? (<Spin />) : (<div><p>Name: {text}</p><Divider /><p>Width: {data?.width}</p><p>Height: {data?.height}</p><p>Top: {data?.top}</p><p>Left: {data?.left}</p></div>)}trigger="hover"visible={show}onVisibleChange={(visible) => setShow(visible)}><Button type="link" onMouseEnter={onClick} disabled={loading}>{text}</Button></Popover>);
};export const columns = [{title: "Name",dataIndex: "name",render: (text) => <RenderNameCom text={text} />,},
];const testPage = () => {return (<Tablestyle={{ paddingTop: "100px" }}columns={columns}dataSource={[{ name: "John Doe", age: 32 }]}/>);
};export default testPage;
3.2 hover時長判斷
判斷鼠標hover時長,決定是否觸發事件;基礎代碼模擬。
const HoverTimer = () => {const [loading, setLoading] = useState(false);const timer = useRef(null);const onMouseEnter = async () => {timer.current = setTimeout(async () => {try {setLoading(true);await delay(2000);console.log("clicked");setLoading(false);} catch (error) {console.log(error);setLoading(false);}}, 1000);};const onMouseLeave = () => {if (timer.current) {clearTimeout(timer.current);}};return (<Buttontype="link"onMouseEnter={onMouseEnter}onMouseLeave={onMouseLeave}loading={loading}>Hover me</Button>);
};
3.3 render+hover
- hover會自動展開和關閉,可以不再設置show的狀態。
- 注意hover剛開始,定時器未執行,利用defaultData的初始狀態進行設置loading
import { Table } from "antd";
import React, { useState, useRef } from "react";
import { Button, Popover, Spin, Divider } from "antd";const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));const RenderNameCom = ({ text }) => {const [loading, setLoading] = useState(false);const defaultData = {width: 0,height: 0,top: 0,left: 0,};const [data, setData] = useState(defaultData);const timer = useRef(null);const onMouseEnter = async () => {console.log("clicked start");setData(defaultData); // 同步清空timer.current = setTimeout(async () => {try {setLoading(true);await delay(2000);setData({width: 100,height: 100,top: 100,left: 100,});console.log("clicked");setLoading(false);} catch (error) {console.log(error);setLoading(false);}}, 1000);};const onMouseLeave = () => {if (timer.current) {clearTimeout(timer.current);}};return (<Popovercontent={loading || data?.width === 0 ? (<Spin />) : (<div><p>Name: {text}</p><Divider /><p>Width: {data?.width}</p><p>Height: {data?.height}</p><p>Top: {data?.top}</p><p>Left: {data?.left}</p></div>)}trigger="hover"><Buttontype="link"onMouseEnter={onMouseEnter}onMouseLeave={onMouseLeave}disabled={loading}>{text}</Button></Popover>);
};export const columns = [{title: "Name",dataIndex: "name",render: (text) => <RenderNameCom text={text} />,},
];const testPage = () => {return (<div><Tablestyle={{ paddingTop: "100px" }}columns={columns}dataSource={[{ name: "John Doe", age: 32 }]}/></div>);
};export default testPage;