refactor: 移除未使用的 RouterView 组件,优化 a2use 组件的模板和 SafeNFormItem 的实现
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { RouterView } from 'vue-router';
|
|
||||||
import AppNaiveUIProvider from './AppNaiveUIProvider.vue';
|
import AppNaiveUIProvider from './AppNaiveUIProvider.vue';
|
||||||
import A2use from './utils/a2use.vue';
|
import A2use from './utils/a2use.vue';
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ function handleValidateClick() {
|
|||||||
<template>
|
<template>
|
||||||
<div p-4>
|
<div p-4>
|
||||||
<div border>
|
<div border>
|
||||||
<div>formValue: {{ JSON.stringify(formValue) }}</div>
|
<div>
|
||||||
|
<pre>formValue: {{ JSON.stringify(formValue, null, 2) }}</pre>
|
||||||
|
</div>
|
||||||
<div>get(formValue, 'user.name'): {{ get(formValue, 'user.name') }}</div>
|
<div>get(formValue, 'user.name'): {{ get(formValue, 'user.name') }}</div>
|
||||||
</div>
|
</div>
|
||||||
<n-space mt-4>
|
<n-space mt-4>
|
||||||
@@ -44,7 +46,7 @@ function handleValidateClick() {
|
|||||||
|
|
||||||
<n-space item-class="flex-1">
|
<n-space item-class="flex-1">
|
||||||
<n-card title="SafeForm" mt-4>
|
<n-card title="SafeForm" mt-4>
|
||||||
<SafeNForm>
|
<SafeNForm label-placement="left" label-width="auto">
|
||||||
<n-form-item
|
<n-form-item
|
||||||
label="姓名"
|
label="姓名"
|
||||||
path="user.name"
|
path="user.name"
|
||||||
@@ -53,6 +55,15 @@ function handleValidateClick() {
|
|||||||
<n-input v-model:value="formValue.user.name" placeholder="输入姓名" />
|
<n-input v-model:value="formValue.user.name" placeholder="输入姓名" />
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
|
|
||||||
|
<SafeNFormItem
|
||||||
|
#default="{ value, setValue }"
|
||||||
|
:rule="{ required: true, message: '请输入姓名', trigger: ['input'] }"
|
||||||
|
label="姓名"
|
||||||
|
path="user.name"
|
||||||
|
>
|
||||||
|
<NInput :value="value" placeholder="SafeNFormItem" @update:value="setValue" />
|
||||||
|
</SafeNFormItem>
|
||||||
|
|
||||||
<n-form-item
|
<n-form-item
|
||||||
label="电话号码"
|
label="电话号码"
|
||||||
path="phone"
|
path="phone"
|
||||||
@@ -61,14 +72,6 @@ function handleValidateClick() {
|
|||||||
<n-input v-model:value="formValue.phone" placeholder="电话号码" />
|
<n-input v-model:value="formValue.phone" placeholder="电话号码" />
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
|
|
||||||
<SafeNFormItem #default="slotProps" path="user.name">
|
|
||||||
<div class="border">
|
|
||||||
<!-- <pre>{{ JSON.stringify({ slotProps: toRaw(slotProps) }, null, 2) }}</pre> -->
|
|
||||||
<div>v: {{ slotProps.value }}</div>
|
|
||||||
</div>
|
|
||||||
<NInput v-model:value="slotProps.value" placeholder="SafeNFormItem" />
|
|
||||||
</SafeNFormItem>
|
|
||||||
|
|
||||||
<n-form-item>
|
<n-form-item>
|
||||||
<n-button attr-type="button" @click="handleValidateClick"> 验证 </n-button>
|
<n-button attr-type="button" @click="handleValidateClick"> 验证 </n-button>
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
// https://www.naiveui.com/zh-CN/os-theme/components/form
|
/**
|
||||||
// initialFormValue
|
* https://www.naiveui.com/zh-CN/os-theme/components/form
|
||||||
|
*
|
||||||
|
* FIXME: `NForm` 和 `NFormItem` 的 slots 还没有实现。`NFormItemGi`组件。
|
||||||
|
*/
|
||||||
|
|
||||||
import { get, set } from 'lodash-es';
|
import { get, set } from 'lodash-es';
|
||||||
import type { FormInst } from 'naive-ui';
|
import type { FormInst, FormItemProps, FormProps } from 'naive-ui';
|
||||||
|
import { NForm, NFormItem, formItemProps, NInput, formProps } from 'naive-ui';
|
||||||
import type { Get, Paths } from 'type-fest';
|
import type { Get, Paths } from 'type-fest';
|
||||||
import type { SlotsType } from 'vue';
|
import type { SlotsType } from 'vue';
|
||||||
|
import { Comment } from 'vue';
|
||||||
|
|
||||||
type UseSafeNFormOptions<T> = {
|
type UseSafeNFormOptions<FormValue> = {
|
||||||
initialFormValue?: T;
|
initialFormValue?: FormValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function useSafeNForm<T extends Record<string, any> = Record<string, unknown>>(
|
export function useSafeNForm<T extends Record<string, any> = Record<string, unknown>>(
|
||||||
@@ -17,9 +22,8 @@ export function useSafeNForm<T extends Record<string, any> = Record<string, unkn
|
|||||||
const formValue = ref<T>(structuredClone(toRaw(options.initialFormValue)) || ({} as T));
|
const formValue = ref<T>(structuredClone(toRaw(options.initialFormValue)) || ({} as T));
|
||||||
|
|
||||||
// 创建类型安全的 Form 组件
|
// 创建类型安全的 Form 组件
|
||||||
interface SafeNFormProps {
|
type SafeNFormProps = FormProps;
|
||||||
disabled?: boolean;
|
|
||||||
}
|
|
||||||
type SafeNFormSlots = SlotsType<{
|
type SafeNFormSlots = SlotsType<{
|
||||||
default?: { count?: number };
|
default?: { count?: number };
|
||||||
}>;
|
}>;
|
||||||
@@ -28,8 +32,7 @@ export function useSafeNForm<T extends Record<string, any> = Record<string, unkn
|
|||||||
(props, ctx) => {
|
(props, ctx) => {
|
||||||
return () => (
|
return () => (
|
||||||
<NForm
|
<NForm
|
||||||
inline={!true}
|
{...props}
|
||||||
label-width="auto"
|
|
||||||
model={formValue.value}
|
model={formValue.value}
|
||||||
ref={(inst) => {
|
ref={(inst) => {
|
||||||
formRef.value = inst as unknown as FormInst;
|
formRef.value = inst as unknown as FormInst;
|
||||||
@@ -42,20 +45,19 @@ export function useSafeNForm<T extends Record<string, any> = Record<string, unkn
|
|||||||
{
|
{
|
||||||
name: 'SafeNForm',
|
name: 'SafeNForm',
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
props: ['disabled'],
|
props: formProps,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
// <<<<<
|
// <<<<<
|
||||||
|
|
||||||
// >>>>> 创建类型安全的 FormItem 组件
|
// >>>>> 创建类型安全的 FormItem 组件
|
||||||
type SafeNFormItemProps<P extends Paths<T> & string> = {
|
type SafeNFormItemProps<P extends Paths<T> & string> = FormItemProps & {
|
||||||
label?: string;
|
|
||||||
path: P;
|
path: P;
|
||||||
placeholder?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type SafeNFormItemDefaultSlot<P extends Paths<T> & string> = {
|
type SafeNFormItemDefaultSlot<P extends Paths<T> & string> = {
|
||||||
value: Get<T, P>;
|
value: Get<T, P>;
|
||||||
|
setValue: (val: Get<T, P>) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const SafeNFormItemImpl = defineComponent<
|
const SafeNFormItemImpl = defineComponent<
|
||||||
@@ -66,18 +68,25 @@ export function useSafeNForm<T extends Record<string, any> = Record<string, unkn
|
|||||||
>(
|
>(
|
||||||
(props, ctx) => {
|
(props, ctx) => {
|
||||||
return () => {
|
return () => {
|
||||||
// const value = get(formValue.value, props.path) as Get<T, typeof props.path>;
|
const value = get(formValue.value, props.path);
|
||||||
const value = computed({
|
function setValue(val: typeof value) {
|
||||||
get() {
|
set(formValue.value, props.path, val);
|
||||||
return get(formValue.value, props.path) as Get<T, typeof props.path>;
|
}
|
||||||
},
|
|
||||||
set(v) {
|
const defaultSlotContent = ctx.slots.default?.({
|
||||||
set(formValue.value, props.path, v);
|
value,
|
||||||
},
|
setValue,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 如果没有提供默认 slot 内容,则渲染一个 NInput 作为默认输入组件
|
||||||
|
const renderDefaultNInput = defaultSlotContent?.some((v) => v.type !== Comment) ? null : (
|
||||||
|
<NInput value={value} onUpdate:value={setValue} />
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NFormItem path={props.path} label={props.label}>
|
<NFormItem {...props} path={props.path}>
|
||||||
{ctx.slots.default?.({ value: value.value })}
|
{defaultSlotContent}
|
||||||
|
{renderDefaultNInput}
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -85,7 +94,7 @@ export function useSafeNForm<T extends Record<string, any> = Record<string, unkn
|
|||||||
{
|
{
|
||||||
name: 'SafeNFormItem',
|
name: 'SafeNFormItem',
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
props: ['label', 'path', 'placeholder'],
|
props: Object.keys(formItemProps) as unknown as [keyof FormItemProps],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user