平时用到的一些代码片段

平时用到的一些代码片段

介绍

新年快乐🐯 🎆
这里介绍的是平常可能会用到的一些代码片段,可能对各位有点帮助,文章会持续更新✿✿ヽ(°▽°)ノ✿

正文

  • antd
  • 内部控制visible
  • 外部控制是否可关闭

typescript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import React, { forwardRef, useImperativeHandle, useRef, useCallback, useState } from 'react'
import { Modal, Button } from 'antd'
import { ModalProps } from 'antd/es/modal'

type TModalRef = {
open: (value?: any) => void
}

type TModalProps = {
// any props
} & Partial<ModalProps>

// modal
const InternalVisibleModal = forwardRef<TModalRef, TModalProps>((props, ref) => {

const {
onCancel: propsOnCancel,
onOk: propsOnOk
} = props

const [ visible, setVisible ] = useState<boolean>(false)

const open = useCallback((value?: any) => {
console.log(value)
setVisible(true)
}, [])

const onCancel = useCallback((e) => {
const result = propsOnCancel?.(e)
if(typeof result !== 'boolean' || result) {
setVisible(false)
}
}, [propsOnCancel])

const onOk = useCallback((e) => {
const result = propsOnOk?.(e)
if(typeof result !== 'boolean' || result) {
setVisible(false)
}
}, [propsOnOk])

useImperativeHandle(ref, () => {
return {
open
}
}, [open])

return (
<Modal
visible={visible}
onCancel={onCancel}
onOk={onOk}
title='自定义modal'
>
hello world
</Modal>
)

})

// parent
const ParentComponent = () => {

const modalRef = useRef<TModalRef>(null)

return (
<>
<Button onClick={() => {
modalRef.current?.open()
}}>open</Button>
<InternalVisibleModal
ref={modalRef}
/>
</>
)

}


javascript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import React, { forwardRef, useImperativeHandle, useRef, useCallback, useState } from 'react'
import { Modal, Button } from 'antd'

// modal
const InternalVisibleModal = forwardRef((props, ref) => {

const {
onCancel: propsOnCancel,
onOk: propsOnOk
} = props

const [ visible, setVisible ] = useState(false)

const open = useCallback((value) => {
console.log(value)
setVisible(true)
}, [])

const onCancel = useCallback((e) => {
const result = propsOnCancel?.(e)
if(typeof result !== 'boolean' || result) {
setVisible(false)
}
}, [propsOnCancel])

const onOk = useCallback((e) => {
const result = propsOnOk?.(e)
if(typeof result !== 'boolean' || result) {
setVisible(false)
}
}, [propsOnOk])

useImperativeHandle(ref, () => {
return {
open
}
}, [open])

return (
<Modal
visible={visible}
onCancel={onCancel}
onOk={onOk}
title='自定义modal'
>
hello world
</Modal>
)

})

// parent
const ParentComponent = () => {

const modalRef = useRef(null)

return (
<>
<Button onClick={() => {
modalRef.current?.open()
}}>open</Button>
<InternalVisibleModal
ref={modalRef}
/>
</>
)

}

html2canvas

typescript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import html2canvas, { Options } from 'html2canvas';

async function captureCover(
query: string,
html2canvasOptions: Partial<Options> = {},
) {
const element: HTMLElement | null = document.querySelector(query);

if (!element) return Promise.reject();

const { width, height } = element.getBoundingClientRect() || {};

const options: Partial<Options> = {
useCORS: true, //允许跨域图片
allowTaint: true, //允许跨域图片
logging: true,
width,
height,
scrollY: 0,
scrollX: 0,
backgroundColor: 'rgba(0, 0, 0, 0)',
...html2canvasOptions,
};

return new Promise<Blob>((resolve, reject) => {
html2canvas(element as any, options).then(function (context) {
context.toBlob(
(data) => {
if (data) {
resolve(data);
} else {
reject();
}
},
'image/png',
0.9,
);
});
});
}

javascript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import html2canvas from 'html2canvas';

async function captureCover(
query,
html2canvasOptions
) {
const element = document.querySelector(query);

if (!element) return Promise.reject();

const { width, height } = element.getBoundingClientRect() || {};

const options = {
useCORS: true, //允许跨域图片
allowTaint: true, //允许跨域图片
logging: true,
width,
height,
scrollY: 0,
scrollX: 0,
backgroundColor: 'rgba(0, 0, 0, 0)',
...html2canvasOptions,
};

return new Promise((resolve, reject) => {
html2canvas(element, options).then(function (context) {
context.toBlob(
(data) => {
if (data) {
resolve(data);
} else {
reject();
}
},
'image/png',
0.9,
);
});
});
}

jspdf

typescript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import jsPDF from 'jspdf'
import html2Canvas, { Options } from 'html2canvas'

const A4_RATIO = 630 / 891

export const html2Pdf = async (query: string, canvasOpts: Partial<Options>={}) => {

const element: HTMLElement | null = document.querySelector(query)

if(!element) return Promise.reject()

const originWidth = element.offsetWidth
const originHeight = element.offsetHeight

const scale = 595.28 / originWidth
const scaleCanvas = document.createElement('canvas')
scaleCanvas.width = 595.28
scaleCanvas.height = originHeight * scale

var opts: Partial<Options> = {
useCORS: true,//允许跨域图片
allowTaint: true,//允许跨域图片
logging: true,
width: originWidth,
height: originHeight,
scrollY: 0,
scrollX: 0,
canvas: scaleCanvas,
scale,
backgroundColor: "rgba(0, 0, 0, 0)",
onclone: (document) => {
const deleteStyleKeys = ['transform', 'transition', 'boxShadow']
const element: HTMLElement | null = document.querySelector(query)
if(!element) return
deleteStyleKeys.forEach((key) => ((element.style as any)[key] = ''))
},
...canvasOpts
};
return new Promise((resolve, reject) => {
html2Canvas(element, opts).then(function (context) {

let contentWidth = context.width
let contentHeight = context.height
let pageHeight = contentWidth / A4_RATIO
let leftHeight = contentHeight
let position = 0

let pageData = context.toDataURL('image/png', 0.9)

let PDF = new jsPDF('', 'pt', 'a4')
if (leftHeight <= pageHeight) {
PDF.addImage(pageData, 'PNG', 0, 0, contentWidth, contentHeight)
} else {
while (leftHeight >= 20) {
PDF.addImage(pageData, 'PNG', 0, position, contentWidth, contentHeight)
leftHeight -= pageHeight
position -= pageHeight
if (leftHeight >= 20) {
PDF.addPage()
}
}
}

resolve(PDF.output('blob'))

})
})
}

SuperPartial

  • typescript
  • Partial 深层次版本

typescript

1
2
3
type SuperPartial<T> = {
[K in keyof T]?: SuperPartial<T[K]>
}

withTry

  • 工具方法
  • 异步错误捕获

typescript

1
2
3
4
5
6
7
8
9
10
function withTry<T=any> (func: Function) {
return async function(...args: any[]): Promise<[any, T | null]> {
try {
const data = await func(...args)
return [null, data]
}catch(err) {
return [err, null]
}
}
}

javascript

1
2
3
4
5
6
7
8
9
10
function withTry (func) {
return async function(...args) {
try {
const data = await func(...args)
return [null, data]
}catch(err) {
return [err, null]
}
}
}

sleep

  • 延迟方法

javascript

1
2
3
async function sleep(time=1000) {
return new Promise(resolve => setTimeout(resolve, time))
}

最近几天

1
2
3
4
5
6
7
8
9
function getRecentDay(day, customDate) {
const date = customDate ? new Date(customDate) : new Date()
const today = date.getTime()
const oneDayMill = 1000 * 60 * 60 * 24
return new Array(day).fill(0).map((_, index) => {
return new Date(today - (day - index - 1) * oneDayMill)
})
}

最近2天:getRecentDay(2)
2022-12-22的最近2天:getRecentDay(2, '2022-12-22')

本周

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function getThisWeek(customDate) {
const date = customDate ? new Date(customDate) : new Date()
const time = date.getTime()
const oneDayMill = 1000 * 60 * 60 * 24
const day = date.getDay() || 7
const dayPrev = day
const dayNext = 7 - day
return [
...new Array(dayPrev).fill(0).map((_, index) => {
return new Date(time - oneDayMill * (dayPrev - index - 1))
}),
...new Array(dayNext).fill(0).map((_, index) => {
return new Date(time + oneDayMill * (index + 1))
}),
]
}

本周:getThisWeek()
2022-12-22当周:getThisWeek('2022-12-22')

本月

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0
}

function getMonthDay(date) {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day30Month = [4, 6, 9, 11]
if(month == 2) {
if(isLeapYear(year)) return 29
return 28
}
return day30Month.includes(month) ? 30 : 31
}

function getThisMonth(customDate) {
const date = customDate ? new Date(customDate) : new Date()
const time = date.getTime()
const oneDayMill = 1000 * 60 * 60 * 24
const day = date.getDate()
const monthDay = getMonthDay(date)
const dayPrev = day
const dayNext = monthDay - day
return [
...new Array(dayPrev).fill(0).map((_, index) => {
return new Date(time - oneDayMill * (dayPrev - index - 1))
}),
...new Array(dayNext).fill(0).map((_, index) => {
return new Date(time + oneDayMill * (index + 1))
}),
]
}

本月:getThisMonth()
2022-11-22当月:getThisMonth('2022-11-22')

本年

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0
}

function getThisYear(customDate) {
const date = customDate ? new Date(customDate) : new Date()
const oneDayMill = 1000 * 60 * 60 * 24
const year = date.getFullYear()
const startDate = new Date(`${year}`).getTime()

return new Array(isLeapYear(year) ? 366 : 365).fill(0).map((_, index) => {
return new Date(startDate + oneDayMill * index)
})
}

h5无限滚动(mobile2)

javascript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import React from 'react'
import {
ListView,
Flex,
Icon,
} from 'antd-mobile'
import { Component as RefastComponent } from 'refast'

export default class extends RefastComponent {

constructor(props) {
super(props, logic)
const dataSource = new ListView.DataSource({
rowHasChanged: (row1, row2) => {
return row1 == row2
}
})
this.state = {
dataSource: dataSource.cloneWithRows({}),
originValue: [],
fetchLoading: false,
page: 1,
pageSize: 10,
total: 0,
}
}

row = (rowData, sectionID, rowID) => {
const { originValue } = this.state
const { } = rowData
return (
<div>

</div>
)
}

componentDidMount = async () => {
this.add_list_Listener()
await this.fetchData()
}

componentWillUnmount () {
this.remove_list_Listener()
}

//增加监听
add_list_Listener = () => {
if (this.lv && typeof this.lv.getInnerViewNode == "function") {
this.lv.getInnerViewNode().addEventListener('touchstart', this.ts = (e) => {
this.tsPageY = e.touches[0].pageY;
});
const scrollNode = document.scrollingElement ? document.scrollingElement : document.body;
this.lv.getInnerViewNode().addEventListener('touchmove', this.tm = (e) => {
this.tmPageY = e.touches[0].pageY;
if (this.tmPageY > this.tsPageY && this.scrollerTop <= 0 && scrollNode.scrollTop > 0) {
this.domScroller.options.preventDefaultOnTouchMove = false;
} else {
this.domScroller.options.preventDefaultOnTouchMove = undefined;
}
})
}
}

// 移除列表的监听
remove_list_Listener = () => {
if (this.lv && typeof this.lv.getInnerViewNode == "function") {
this.lv.getInnerViewNode().removeEventListener('touchstart', this.ts);
this.lv.getInnerViewNode().removeEventListener('touchmove', this.tm);
}
}

fetchData = async (init = false) => {
this.setState({
fetchLoading: true
})
const { originValue, dataSource, page, pageSize, name, cameraId, startTime, stopTime, status, algoModelType } = this.state
this.dispatch("queryWarnEvent", {
algoModel,
page,
pageSize,
algoModelType,
status,
name,
cameraId,
startTime,
stopTime,
}, (content) => {
const data = content?.data?.list
if (status === "0") {
this.setState({ todoCount: content?.data.total })
}
const newValue = init ? [...data] : [...originValue, ...data]
let newDataSource = dataSource
if (init) {
newDataSource = new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 == row2,
})
}
newDataSource = newDataSource.cloneWithRows(newValue)
this.setState({
originValue: newValue,
dataSource: newDataSource,
fetchLoading: false,
total: content?.data.total
})
})
}

onEndReached = () => {
let { fetchLoading, page, originValue, total } = this.state
if (fetchLoading || originValue.length >= total) {
return
}
this.setState({ page: page + 1 }, this.fetchData)
}

render () {
const { dataSource, fetchLoading } = this.state
return (
<ListView
className="warning-list"
ref={el => this.lv = el}
dataSource={dataSource}
renderFooter={() => {
return (
<div style={{ padding: 30, textAlign: 'center' }}>
{fetchLoading ? <Icon type="loading" /> : '没有更多了'}
</div>
)
}}
renderRow={this.row}
style={{
height: '100vh',
overflow: 'auto',
}}
pageSize={10}
scrollRenderAheadDistance={500}
onEndReached={this.onEndReached}
onEndReachedThreshold={10}
/>
)
}

}

h5表单容器(mobile2)

javascript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import {
Picker as AntPicker,
Icon,
} from 'antd-mobile'

const CustomChildren = ({extra, onClick, children}) => (
<div
onClick={onClick}
style={{
backgroundColor: '#F3F4F7',
lineHeight: '3.2rem',
fontSize: '1.3rem',
textAlign: 'left',
overflow: 'hidden',
padding: '0 .4rem',
borderRadius: 6
}}
>
{children}
<span style={{color: 'black'}}>{extra}</span>
</div>
)


const Picker = () => {

return (
<AntPicker
cols={1}
>
<CustomChildren>
<span style={{float: 'right', display: 'flex', height: '3.2rem', alignItems: 'center', color: "#D8D8D8"}}>
<Icon type="down"/>
</span>
</CustomChildren>
</AntPicker>
)

}

useDeepEffect

typescript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { useEffect, useRef, EffectCallback, DependencyList } from 'react';
import { isEqual } from 'lodash';

function useDeepEffect(fn: EffectCallback, deps: DependencyList) {
const isFirst = useRef(true);
const prevDeps = useRef(deps);

useEffect(() => {
const isSame = prevDeps.current.every((obj, index) =>
isEqual(obj, deps[index]),
);

if (isFirst.current || !isSame) {
fn();
}

isFirst.current = false;
prevDeps.current = deps;
}, deps);
}

export default useDeepEffect;

useStateChange

typescript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import { useState, useEffect, useCallback, useRef } from 'react';

type StateChangeReturnType<T> = [
T,
(value: T | ((prev: T) => T), callback?: () => void) => void,
];

function useStateChange<T = any>(initialValue: T): StateChangeReturnType<T> {
const [value, setValue] = useState<T>(initialValue);
const callbackRef = useRef<any>();

const realSetValue = useCallback(
(value: T | ((prev: T) => T), callback?: () => void) => {
callbackRef.current = callback;
setValue((prev) => {
const result =
typeof value === 'function' ? (value as (prev: T) => T)(prev) : value;
return result;
});
},
[],
);

useEffect(() => {
callbackRef.current?.();
}, [value]);

return [value, realSetValue];
}

export default useStateChange;

结束

到这里结束,希望对各位有帮助。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!