-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
wip: 重构 Picker 组件 对齐 mobile-vue #514
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,68 +1,133 @@ | ||
import React, { FC, useMemo } from 'react'; | ||
import React, { FC, useState, MouseEvent, useEffect } from 'react'; | ||
import useDefaultProps from 'tdesign-mobile-react/hooks/useDefaultProps'; | ||
import isBoolean from 'lodash/isBoolean'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这里的tdesign-mobile-react引入是不是错了? |
||
import isString from 'lodash/isString'; | ||
import useConfig from '../_util/useConfig'; | ||
import useDefault from '../_util/useDefault'; | ||
import withNativeProps, { NativeProps } from '../_util/withNativeProps'; | ||
import PickerView, { getPickerViewDefaultValue } from './PickerView'; | ||
import { NativeProps } from '../_util/withNativeProps'; | ||
import { pickerDefaultProps } from './defaultProps'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 在common.ts里引入classname和style的 type |
||
import { TdPickerProps } from './type'; | ||
import Button from '../button'; | ||
import Popup from '../popup'; | ||
import { TdPickerProps, PickerColumnItem, PickerValue } from './type'; | ||
import { PickerColumn } from '.'; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这里是哪里引入的? |
||
import PickerItem, { type PickerItemExposeRef } from './PickerItem'; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 单独一行引入类型吧 |
||
export interface PickerProps extends TdPickerProps, NativeProps {} | ||
|
||
function getDefaultText(prop: unknown, defaultText: string): string { | ||
if (isString(prop)) return prop; | ||
if (isBoolean(prop)) return defaultText; | ||
return; | ||
} | ||
|
||
Comment on lines
+16
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这里的类型返回不是还有undefined嘛? |
||
const getIndexFromColumns = (column: PickerColumn, value: PickerValue) => { | ||
if (!value) return 0; | ||
return column?.findIndex((item: PickerColumnItem) => item.value === value); | ||
}; | ||
|
||
const Picker: FC<PickerProps> = (props) => { | ||
const { | ||
visible, | ||
value, | ||
defaultValue, | ||
cancelBtn, | ||
confirmBtn, | ||
title, | ||
header, | ||
footer, | ||
children, | ||
onCancel, | ||
onConfirm, | ||
onChange, | ||
} = props; | ||
const { value, onChange, defaultValue, columns, onConfirm, onCancel, onPick, title, header } = useDefaultProps( | ||
props, | ||
pickerDefaultProps, | ||
); | ||
|
||
const { classPrefix } = useConfig(); | ||
const name = `${classPrefix}-picker`; | ||
|
||
Comment on lines
33
to
34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 使用usePrefixClass |
||
const internalDefaultValue = useMemo( | ||
() => getPickerViewDefaultValue(defaultValue, children), | ||
[defaultValue, children], | ||
); | ||
const [pickerValue, setPickerValue] = useDefault(value, defaultValue, onChange); | ||
const confirmButtonText = getDefaultText(props.confirmBtn, undefined); | ||
const cancelButtonText = getDefaultText(props.cancelBtn, undefined); | ||
const [curValueArray, setCurValueArray] = useState(pickerValue.map((item) => item) || []); | ||
Comment on lines
+37
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 使用props解构的值,统一一下 |
||
|
||
const realColumns = typeof columns === 'function' ? columns(curValueArray) : columns; | ||
const curIndexArray = realColumns.map((item: PickerColumn, index: number) => getIndexFromColumns(item, index)); | ||
const [pickerItemInstanceArray, setPickerItemInstanceArray] = useState<PickerItemExposeRef[]>([]); | ||
|
||
const setPickerItemRef = (instance: PickerItemExposeRef, idx: number) => { | ||
setPickerItemInstanceArray((prev) => { | ||
const copy = [...prev]; | ||
copy[idx] = instance; | ||
return copy; | ||
}); | ||
}; | ||
|
||
const [internalValue, setInternalValue] = useDefault(value, internalDefaultValue, onChange); | ||
function handleConfirm(e: MouseEvent<HTMLDivElement>) { | ||
const target = realColumns.map((item, idx) => item[curIndexArray[idx]]); | ||
const label = target.map((item) => item.label); | ||
const value = target.map((item) => item.value); | ||
setPickerValue(value, { | ||
columns: [], | ||
e, | ||
}); | ||
onConfirm(value, { index: curIndexArray, e, label }); | ||
} | ||
function handleCancel(e: MouseEvent<HTMLDivElement>) { | ||
pickerItemInstanceArray.forEach((item, idx) => { | ||
item?.setIndex(curIndexArray[idx]); | ||
}); | ||
onCancel({ e }); | ||
} | ||
|
||
function handlePick(context: any, column: number) { | ||
const { index } = context; | ||
|
||
curIndexArray[column] = index; | ||
curValueArray[column] = realColumns[column][index]?.value; | ||
|
||
onPick(curValueArray, { index, column }); | ||
} | ||
|
||
useEffect(() => { | ||
setCurValueArray(pickerValue.map((item) => item)); | ||
}, [pickerValue]); | ||
|
||
useEffect(() => { | ||
realColumns.forEach((col: PickerColumn, idx: number) => { | ||
const index = col.findIndex((item) => item.value === curValueArray[idx]); | ||
curIndexArray[idx] = index > -1 ? index : 0; | ||
pickerItemInstanceArray[idx]?.setIndex(curIndexArray[idx]); | ||
}); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [realColumns, curIndexArray]); | ||
|
||
return ( | ||
<Popup visible={visible} placement="bottom"> | ||
{withNativeProps( | ||
props, | ||
<div className={name}> | ||
{header === true ? ( | ||
<div className={`${name}__toolbar`}> | ||
<Button className={`${name}__cancel`} variant="text" onClick={(e) => onCancel?.({ e })}> | ||
{cancelBtn} | ||
</Button> | ||
<div className={`${name}__title`}>{title}</div> | ||
<Button className={`${name}__confirm`} variant="text" onClick={(e) => onConfirm?.(internalValue, { e })}> | ||
{confirmBtn} | ||
</Button> | ||
</div> | ||
) : ( | ||
header | ||
)} | ||
{/* TODO:popup集成惰性加载后可移除条件渲染 */} | ||
{visible && ( | ||
<PickerView value={internalValue} onChange={setInternalValue}> | ||
{children} | ||
</PickerView> | ||
)} | ||
{footer} | ||
</div>, | ||
)} | ||
</Popup> | ||
<div className={name}> | ||
<div className={`${name}__toolbar`}> | ||
{cancelButtonText ? ( | ||
<div className={`${name}__cancel`} onClick={handleCancel}> | ||
{cancelButtonText} | ||
</div> | ||
) : null} | ||
|
||
<div className={`${name}__title`}>{title}</div> | ||
|
||
{confirmButtonText ? ( | ||
<div className={`${name}__confirm`} onClick={handleConfirm}> | ||
{confirmButtonText} | ||
</div> | ||
) : null} | ||
</div> | ||
{header} | ||
|
||
<div className={`${name}__main`}> | ||
{realColumns.map((item, idx) => ( | ||
<div key={idx} className={`${name}-item__group`}> | ||
<PickerItem | ||
ref={(instance) => { | ||
setPickerItemRef(instance, idx); | ||
}} | ||
options={item} | ||
value={pickerValue[idx]} | ||
renderLabel={props.renderLabel} | ||
onPick={(context: any) => handlePick(context, idx)} | ||
/> | ||
</div> | ||
))} | ||
|
||
<div className={`${name}__mask ${name}__mask--top`}></div> | ||
<div className={`${name}__mask ${name}__mask--bottom`}></div> | ||
<div className={`${name}__indicator`}></div> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type 单独引入