MS Snippet 代码片段
日常开发中常用的 react 代码片段
支持的语言类型
- Typescript (.ts)
- Typescript React (.tsx)
基础的代码片段
Prefix |
Body |
cl |
console.log($1) |
div |
<div className={styles.$1}></div> |
imp |
import ${2:moduleName} from '${1:module}';$0 |
imd |
import { $2 } from '${1:module}';$0 |
us |
const [$1, set${1/(.*)/${1:/capitalize}/}] = useState<$2>($3) |
um |
const $1 = useMemo(() => {return $2}, [$3]) |
uref |
const $1 = useRef<$2>() |
ue |
useEffect(() => {$0}, [$1]) |
con |
const { $2 } = $1 |
arro |
const $1 = ($2) => {$0} |
if |
if ($1) {$2} |
inter |
interface I$1 {$2} |
mss |
message.success('$1') |
msr |
message.error('$1') |
ims |
import styles from './index.less' |
td |
// TODO: $1 |
opt |
{value:'$1',label:'$2'} |
clas |
className={styles.$1} |
req |
export const $1= (params) => {return request('$2', params) } |
m-fv
form.validateFields().then((values) => {
console.log(values);
});
m-useR
const {
data: selfData,
loading,
run,
} = useRequest(fetch, {
manual: true,
onSuccess: () => {
// TODO:
},
});
m-col
const columns: ColumnsType<type>[] = [
{
title: "",
dataIndex: "",
},
];
m-con
const conditions: ICondition[] = [
{
type: "select",
label: "",
name: "",
itemProps: {
options: [],
},
},
];
m-sea
const searchProps = {
name: "search",
placeholder: "请输入",
allowClear: true,
};
m-usm
import { useModalVisible } from "@moresec/hooks";
const { visible, show, hide } = useModalVisible();
m-query-param
import { useQueryParam } from '@moresec/hooks',
const { query, updateQuery } = useQueryParam<$1>($2)
m-react
import React from "react";
interface IProps {}
const App: React.FC<IProps> = (props) => {
return <div></div>;
};
export default App;
m-sp
const searchParams = getSearchParams(window.location.search);
const { page = 1, pageSize = 10, ...resetParams } = searchParams;
m-dep
<Item dependencies={[]} noStyle>
{({ getFieldValue }) => {
return <></>;
}}
</Item>
m-access
import { useAccess } from "umi";
const {} = useAccess();
m-ell
<MSEllipsis value={$1} lineClamp={$2} />
m-list
<MSList
dataList={[
{ label: "AA", value: "aa" },
{ label: "BB", value: "bb", hidden: true },
]}
rowProps={{ gutter: 30 }}
/>
m-tabs
<Tabs defaultActiveKey="a" destroyInactiveTabPane={true}>
<Tabs.TabPane tab="A" key="a">
children
</Tabs.TabPane>
</Tabs>
m-tabs-page
import { Tabs } from 'antd'
import React from 'react'
import { history } from 'umi'
const items = [
{ label: '页面1', key: '1' },
{ label: '页面2', key: '2' }
]
const Index: React.FC = ({ children }) => {
const search = getSearchParams(location.search)
const tag_id = String(search.tag_id || '') || items[0].key
const setTabId = (tabId: string) => {
const params = new URLSearchParams(location.search)
params.set('tag_id', String(tabId))
history.replace(`${location.pathname}?${params.toString()}`)
}
return (
<>
<Tabs activeKey={tag_id} items={items} onChange={setTabId} />
{children}
</>
)
}
export default Index
<Popconfirm
title={
<>
<div>{title}</div>
<div style={{ marginBottom: 12 }}>
<Form form={form} preserve={false}>
<Form.Item name="name">
<Input />
</Form.Item>
</Form>
</div>
</>
}
destroyTooltipOnHide
onConfirm={() => {
return runSave
}}
>
<Button>按钮</Button>
</Popconfirm>
import { Button, Form, Input } from "antd";
const formItemLayout = {
labelCol: { span: 4 },
wrapperCol: { span: 8 },
};
const { Item } = Form;
const Index = () => {
const [form] = Form.useForm();
const handleFinish = (values: MS.objectAny) => {
// TODO
};
return (
<Form
form={form}
{...formItemLayout}
colon={false}
labelAlign="left"
onFinish={handleFinish}
>
<Item
name="username"
label="名字"
rules={[
{
required: true,
message: "请输入你的名字",
},
]}
>
<Input placeholder="请输入你的名字" />
</Item>
<Item label={null}>
<Button type="primary" htmlType="submit">
确定
</Button>
</Item>
</Form>
);
};
export default Index;
import { useRequest } from "ahooks";
import { Form, Input, Modal } from "antd";
import React, { useEffect } from "react";
import { add, edit } from "@/services/";
const { useForm, Item } = Form;
interface IProps {
visible: boolean;
initialData: MS.objectAny;
onCancel: () => void;
onConfirm: (values: MS.objectAny) => void;
}
const Index = (props: IProps) => {
const { visible, onConfirm, onCancel, initialData } = props;
const [form] = useForm();
const isEdit = Boolean(initialData);
const { loading: loadingAdd, run: runAdd } = useRequest(add, {
manual: true,
onSuccess: () => {
// TODO:
},
});
const { loading: loadingEdit, run: runEdit } = useRequest(edit, {
manual: true,
onSuccess: () => {
// TODO:
},
});
useEffect(() => {
if (visible) {
if (isEdit) {
form.setFieldsValue({
// TODO:
});
} else {
form.resetFields();
}
}
}, [visible, form, isEdit]);
const handleCancel = () => {
form.resetFields();
onCancel();
};
const onFinish = () => {
form.validateFields().then((values) => {
onConfirm(values);
});
};
return (
<Modal
title={`${isEdit ? "编辑" : "新建"}`}
open={visible}
onOk={onFinish}
onCancel={handleCancel}
confirmLoading={loadingAdd || loadingEdit}
>
<Form form={form} labelCol={{ span: 5 }} labelAlign="left">
<Item label="Name" name="name">
<Input />
</Item>
</Form>
</Modal>
);
};
export default Index;
m-df
import { useModalVisible } from "@moresec/hooks";
import { Button, Drawer, Form, Input, Space, Spin } from "antd";
import React from "react";
const { Item: FormItem, useForm } = Form;
export default () => {
const { visible, show: showDrawer, hide: hideDrawer } = useModalVisible();
const [form] = useForm();
const handleSubmit = () => {
form.validateFields().then((values) => {
console.log(values);
hideDrawer();
});
};
const handleClose = () => {
form.resetFields();
hideDrawer();
};
return (
<>
<Button type="primary" onClick={showDrawer}>
抽屉表单
</Button>
<Drawer
title=""
placement="right"
keyboard={true}
width={400}
open={visible}
onClose={handleClose}
maskClosable={false}
footer={
<Space style={{ display: "flex", justifyContent: "flex-end" }}>
<Button ghost type="primary" onClick={handleClose}>
取消
</Button>
<Button
type="primary"
// loading={loading}
onClick={handleSubmit}
>
确定
</Button>
</Space>
}
>
<Spin spinning={false}>
<Form
form={form}
layout="vertical"
labelCol={{ span: 6 }}
labelAlign="right"
>
<FormItem label="$1" name="$1">
<Input />
</FormItem>
</Form>
</Spin>
</Drawer>
</>
);
};
m-dl
import { useModalVisible } from "@moresec/hooks";
import { MSList } from "@moresec/rc-list";
import { Button, Drawer } from "antd";
const Index = () => {
const { visible, show: showDrawer, hide: hideDrawer } = useModalVisible();
const listData = [{ label: "客户名称", value: 123 }];
return (
<>
<Button type="primary" onClick={showDrawer}>
抽屉列表
</Button>
<Drawer
title="标题"
placement="right"
keyboard={true}
width={400}
open={visible}
onClose={hideDrawer}
maskClosable={false}
>
<MSList width="80px" colon={false} dataList={listData} />
</Drawer>
</>
);
};
export default Index;
m-ref
import type { ForwardRefRenderFunction } from "react";
import React, { forwardRef, useImperativeHandle } from "react";
import styles from "./index.less";
interface IProps {}
interface IRef {}
const Index: ForwardRefRenderFunction<IRef, IProps> = (props, ref) => {
useImperativeHandle(ref, () => ({
value: 666,
}));
return <div>index</div>;
};
export default forwardRef(Index);
m-ref-t
import type { ReactElement } from 'react'
import { forwardRef, useImperativeHandle, useRef } from 'react'
interface Props<Q extends object> {
data: Q[]
}
interface Ref<Q extends object> {
value: Q[]
}
/** 使用forwardRef推导出泛型组件的方法 */
export const forwardRefGenerate = <T, R>(
Component: (props: T, ref: React.Ref<R>) => ReactElement | null
) => {
return forwardRef(Component) as unknown as (
props: T & { ref?: React.Ref<R> }
) => ReturnType<typeof Component>
}
export const Index = forwardRefGenerate(
<Q extends object>(props: Props<Q>, ref: React.Ref<Ref<Q>>) => {
const { data } = props
useImperativeHandle(
ref,
() => ({
value: data
}),
[data]
)
return <div>index</div>
}
)
export default Index
// 外部使用
const Fn = () => {
const data = [{ label: 1 }]
const ref = useRef<Ref<(typeof data)[number]>>(null)
return <Index data={data} ref={ref} />
}
m-table
import { useQueryParam } from "@moresec/hooks";
import MSTable from "@moresec/rc-table";
import { useRequest } from "ahooks";
import { Button } from "antd";
import type { ColumnProps, TablePaginationConfig } from "antd/lib/table";
import React from "react";
import styles from "./index.less";
interface Query {
page: number;
page_size: number;
}
const Index = () => {
const initQuery: Query = {
page: 1,
page_size: 10,
};
const { query, updateQuery } = useQueryParam<Query>(initQuery);
const handleTableChange = (
{ current, pageSize }: TablePaginationConfig,
filters: any,
sorter: any
) => {
updateQuery({
page: current,
page_size: pageSize,
});
};
const { data: tableResult, loading } = useRequest(() => fetch, {
refreshDeps: [query],
});
const columns: ColumnProps<any>[] = [
{
title: "",
dataIndex: "",
},
{
title: "操作",
dataIndex: "id",
render: (_, { id }) => <Button type="primary">编辑</Button>,
},
];
return (
<div className={styles.page_wrap}>
<MSTable
loading={loading}
columns={columns}
data={{
list: tableResult?.results || [],
pagination: {
current: query.page,
pageSize: query.page_size,
total: tableResult?.count,
},
}}
onChange={handleTableChange}
/>
</div>
);
};
export default Index;
m-draggable-table
import { MenuOutlined } from "@ant-design/icons";
import DraggableTable from "@moresec/rc-draggable-table";
import { useRequest } from "ahooks";
import type { ColumnProps } from "antd/lib/table";
import React from "react";
import styles from "./index.less";
const Index = () => {
const { data: list, loading: listLoading, refresh } = useRequest(fetch);
const { run: runSort, loading: dragLoading } = useRequest(fetch, {
manual: true,
onSuccess: () => refresh(),
});
const handleDrag = (newdataList: any[]) => {
const ids = newdataList.map((item) => item?.task_id);
runSort({ ids });
};
const columns: ColumnProps<any>[] = [
{
title: "",
dataIndex: "",
},
{
title: "操作",
dataIndex: "id",
},
];
return (
<div className={styles.page_wrap}>
<DraggableTable
loading={listLoading || dragLoading}
columns={columns}
data={{
list: list || [],
pagination: false,
}}
draggable={{
afterDragEnd: (_newIdList: number[], newdataList) =>
handleDrag(newdataList),
dragHandle: (
<MenuOutlined style={{ cursor: "grab", color: "#999" }} />
),
}}
/>
</div>
);
};
export default Index;
m-pro-table
import type { IColumnsType, ProTableRef } from '@moresec/rc-pro-table'
import type { ICondition } from '@moresec/rc-query'
import { Button, message, Modal } from 'antd'
import type { SearchProps } from 'antd/lib/input'
import React, { useRef } from 'react'
import { MSProTable, MSSearch } from '@/components'
import { delete, getList } from '@/services/'
const Index = () => {
const tableRef = useRef<ProTableRef<I.ListReq, I.ListItem>>(null)
const conditions: ICondition[] = [
{
type: 'select',
label: '',
name: '',
itemProps: {
options: []
}
}
]
const columns: IColumnsType<I.ListItem>[] = [
{ title: '', dataIndex: '' },
{
title: '操作',
dataIndex: '',
width: 100,
render: (_, record) => {
const { id } = record
return (
<>
<Button>删除</Button>
</>
)
}
}
]
const handleDelete = (ids: number[]) => {
Modal.confirm({
title: '提示',
content: ``,
onOk: () =>
delete(ids).then(() => {
message.success('删除成功')
tableRef.current?.deleteReload(ids.length)
})
})
}
return (
<MSProTable
tableRef={tableRef}
fetch={getList}
conditions={conditions}
searchProps={{
name: '',
placeholder: '',
render: (_props: SearchProps) => {
const { value, ...rest } = _props
return (
<>
<MSSearch defaultValue={value} {...rest} />
</>
)
}
}}
columns={columns}
batchFooter={{
buttonPosition: 'left',
renderActions(keys = []) {
return (
<Button
type="primary"
disabled={!keys.length}
onClick={() => handleDelete(keys.map(Number))}
>
批量删除
</Button>
)
}
}}
/>
)
}
export default Index
m-pie
import { MSPie } from '@moresec/rc-charts'
import styles from './index.less'
const PieChart: React.FC = props => {
const series = [
{
label: null,
center: ['50%', '50%'],
radius: ['53%', '60%'],
color: ['#9B0707', '#DE3232', '#EB6D10', '#F3C44B', '#59A93F ']
}
]
const legend = [
{
orient: 'horizontal',
top: '50%',
y: 30,
icon: 'circle',
textStyle: {
color: '#000',
fontWeight: 400,
rich: {
a: {
width: 55,
fontSize: 14,
lineHeight: 14
}
}
}
}
]
const tooltip = {
formatter: function (params) {
return params
},
backgroundColor: '#000',
textStyle: { color: '#fff', fontSize: '14px' }
}
const graphic = {
name: 'version',
type: 'text',
left: 'center',
top: '48%',
style: {
text: 'TODO:居中标题',
textAligin: 'center',
fontSize: '14px',
fontWeight: 600,
color: '#333'
}
}
const originalEchartOption = { series, legend, tooltip, graphic }
const data = [{ name: '', value: 1 }]
return (
<div className={styles.chart_wrap}>
<MSPie
style={{ height: '200px', width: '200px' }}
className={styles.pie}
title=""
data={data}
originalEchartsOption={originalEchartOption}
noDataConfig={{ style: { width: '50%', height: '40%' } }}
/>
</div>
)
}
export default PieChart
m-bar
import { MSBar } from '@moresec/rc-charts'
const Bar = () => {
const seriesConfig = {
type: 'bar' as const,
barWidth: 16,
stack: 'all'
}
// TODO:修改
const series = [
{
...seriesConfig,
name: 'name1',
data: [1, 2, 3, 4]
},
{
name: 'name2',
...seriesConfig,
data: [1, 2, 3, 4]
},
{
name: 'name3',
...seriesConfig,
data: [1, 2, 3, 4]
},
{
name: 'name4',
...seriesConfig,
data: [1, 2, 3, 4]
}
]
// TODO:颜色修改
const COLORS = ['#9b0707', '#de3232', '#eb6d10 ', '#f3c44b']
return (
<div>
<MSBar
wrapper={{ height: '' }}
series={series}
grid={{ left: 50, right: '4%', top: 30 }}
xAxis={{
type: 'category',
// TODO:修改
data: ['1', '2', '3', '4', '5'],
axisTick: { show: false }
}}
yAxis={{
name: 'TODO:',
type: 'value',
axisTick: { show: false },
axisLine: { show: false }
}}
color={[...COLORS]}
legend={{
icon: 'circle',
itemGap: '',
itemWidth: '',
itemHeight: '',
data: ['name1', 'name2', 'name3', 'name4']
}}
tooltip={{ order: 'seriesDesc' }}
/>
</div>
)
}
export default Bar