@uiw/react-native
Version:
UIW for React Native
132 lines (131 loc) • 3.51 kB
JavaScript
import React, { useContext } from 'react';
import { isObjectEmpty } from './utils/is';
import { Context } from './hooks/context';
import Card from '../Card';
import Label from './comps/label';
import Tip from './comps/tip';
import { View, SafeAreaView } from 'react-native';
import styles from './styles';
const FormList = ({
formListValue = {
field: '',
type: '',
name: ''
}
}) => {
const {
innerMethods: {
store = {},
updateStore
},
customComponentList
} = useContext(Context);
const {
field,
items = [],
renderAdd,
renderHeader
} = formListValue;
const handleOperate = (type = '', index) => {
let list = store[field] || [];
if (type === 'add') list.push({});
if (type === 'delete') list.splice(index, 1);
// 下移
if (type === 'moveDown') {
if (index !== list.length - 1) {
list[index] = list.splice(index + 1, 1, list[index])[0];
} else {
list.unshift(list.splice(index, 1)[0]);
}
}
// 上移
if (type === 'moveUp') {
if (index !== 0) {
list[index] = list.splice(index - 1, 1, list[index])[0];
} else {
list.push(list.shift());
}
}
// 置顶
if (type === 'moveToTop') {
if (index !== 0) {
list.unshift(list.splice(index, 1)[0]);
}
}
// 置底
if (type === 'moveToBottom') {
if (index !== list.length - 1) {
list.push(list.splice(index, 1)[0]);
}
}
updateStore?.({
store: {
...store,
[field]: list
}
});
};
const change = (fields, value, index) => {
const list = store[field] || [];
const obj = {
...store[field][index],
[fields]: value
};
list.splice(index, 1, obj);
updateStore?.({
store: {
...store,
[field]: list
}
});
};
// 组件渲染
const _renderComponent = (v, index) => {
const values = {
...store[field][index]
};
if (!isObjectEmpty(customComponentList) && Object.keys(customComponentList).includes(v.type)) {
return React.isValidElement(customComponentList[v.type]) ? React.cloneElement(customComponentList[v.type], {
...v,
...v.attr,
value: values[v.field],
onChange: value => change(v.field, value, index)
}) : null;
}
return null;
};
const _render = index => {
return items.map((v, i) => {
const last = items.length - 1 === i;
if (v.hide) {
return null;
}
if (v.type === 'cardList') {
return;
}
return <View key={i} style={styles.form_items_container}>
<View style={[styles.form_items, last && styles.border_none]}>
<Label v={v} />
{_renderComponent(v, index)}
<Tip v={v} />
</View>
</View>;
});
};
return <SafeAreaView style={styles.warpper}>
{(store[field] || []).map((item, index) => <React.Fragment key={index}>
{renderHeader?.(index, {
remove: () => handleOperate('delete', index),
moveUp: () => handleOperate('moveUp', index),
moveDown: () => handleOperate('moveDown', index),
moveToTop: () => handleOperate('moveToTop', index),
moveToBottom: () => handleOperate('moveToBottom', index)
})}
<Card>{_render(index)}</Card>
</React.Fragment>)}
{renderAdd?.({
add: () => handleOperate('add', 0)
})}
</SafeAreaView>;
};
export default FormList;