vee-validate
useForm
useForm是一个自定义组合 API 函数,允许您对useField创建的字段进行分组并聚合它们的状态。它应该用于创建逻辑表单或自定义表单组件,类似于<Form/>组件,它只是useForm的消费者。
import { useForm } from 'vee-validate';
const { errors, errorBag, isSubmitting, isValidating, meta, values, setErrors, setFieldError, setFieldValue, setValues, setFieldTouched, setTouched, validate, validateField, handleSubmit, submitForm, submitCount, resetForm, handleReset, defineField } = useForm({
// 如果为true,则一旦装载了表单组件,它将触发对所有字段的验证。
validateOnMount: true,
// 启用表单级验证,使用指定的架构验证字段。架构可以是有效的 vee-validate 全局验证程序或函数,也可以是 yup 对象架构。
validationSchema: {},
// 表单的初始值可以是响应式对象或引用。
initialValues: { email: '', password: '', },
// 字段的初始错误对于Laravel等非水合SSR应用程序很有用,错误是在挂载时应用的。
initialErrors: {},
// 表单字段的初始触摸状态,应用于已装载。
initialTouched: {},
});
// 一个将字段名映射到其错误消息的对象,如果存在多个字段,它只接受每个字段的第一个错误消息。
errors.value; // 访问错误值
// 一个将字段名称映射到其所有错误消息的对象。
errorBag.value.email; // 电子邮件字段错误
// 指示提交处理程序是否仍在运行,一旦它解决/拒绝,它将再次自动设置为 false。
isSubmitting.value; // true 或 false
// 指示 validate 函数是否仍在运行,一旦 validate 函数完成,它将再次自动设置为 `false`。
isValidating.value; // true 或 false
// 一个计算属性,其中包含一个聚合的元信息/标志,反映表单内所有字段的状态。
meta.value; // { valid: false, invalid: true, dirty: true, .... }
// 一个包含当前表单值的响应式属性,您不应该尝试直接对其进行修改。
values; // { email: 'something@gmail.com', .... }
// 设置多个字段错误消息,内部使用 `setFieldError`
setErrors({
email: 'This field is invalid', // 设置对应值的错误信息
});
// 设置字段的值,如果字段不存在,则不会反映在`值(ref)` 中。这将触发对值已更改的字段的验证。
setFieldValue('email', 'example@gmail.com'); // 设置单个值
// 设置字段的错误消息,这对于设置来自 API 的消息或不可用作验证规则的消息非常有用。将消息设置为 `undefined` 或空字符串可清除错误并将字段标记为有效。
setFieldError('email', 'this email is already taken');
// 设置所有字段值,将触发对已更改字段的验证
setValues({ email: 'example@gmail.com', password: 'p@a$$W0rD',});
// 设置字段的 `touched` meta 标志,如果为不存在的字段设置它,则无效。
setFieldTouched('email', true);
// 设置多个字段 `touched` meta 标志,不验证.
setTouched({ email: true, password: false,});
// 验证所有字段并填充 `errors` 对象,返回一个 Promise,该 Promise 解析为包含所有字段的聚合验证结果的对象。
const { valid, errors } = await validate();
// 验证表单中的特定字段,返回一个 Promise,该 Promise 解析为包含验证结果的对象。
const { valid, errors } = await validateField('email');
// 这是一个用于创建`提交`事件处理程序的高阶函数,您不应该直接将其用作事件的处理程序,而应使用它来创建这些处理程序。
// 使用“onSubmit”作为表单的事件处理程序
const onSubmit = handleSubmit((values, actions) => {
alert(JSON.stringify(values, null, 2));
// 表单对象包含有用的方法
// 设置单个字段值
actions.setFieldValue('field', 'hello');
// 设置多个字段值
actions.setValues({ email: 'value', password: 'hi' });
// 设置单个字段错误
actions.setFieldError('field', 'this field is bad');
// 设置多个字段错误
actions.setErrors({ email: 'bad email', password: 'bad password' });
// 重置表单
actions.resetForm();
// `handleSubmit` 包含一个 `withControlled` 函数,您可以使用该函数仅提交由 `useField` 或 `useFieldModel` 控制的字段。
const onSubmit = handleSubmit.withControlled(values => {
// 仅向API发送受控值
// 仅打印用“useField”或“useFieldModel”声明的字段
alert(JSON.stringify(values, null, 2));});
});
// 用户尝试提交的次数,每当调用 `submitForm` 或 `handleSubmit` 回调时,它都会递增。
submitCount
// 清除错误消息,重置所有字段的元状态,并将其值恢复为初始状态以及 `submitCount` 状态。接受包含新表单状态的可选对象,如果您需要将表单值重置为初始状态以外的其他值,则这很有用。
resetForm({
values: {
firstName: '',
lastName: '',
email: '',
password: '',
},
});
// 默认情况下,`resetForm` 会将之前的初始值与提供的新初始值合并,这意味着只有提供的初始值将被覆盖。您可以通过在第二个参数中传递 `force: true` 来覆盖所有字段。
resetForm({
values: { fname: 'test' }
}, { force: true });
// 清除错误消息,重置所有字段的元状态,并将其值恢复为初始状态以及 `submitCount` 状态。您可以将此函数用作本机表单元素上 `reset` 事件的处理程序。
handleReset();
useFieldArray
useFieldArray是一个自定义的组合 API 函数,允许您管理可重复的字段和表单条目,并提供常用操作帮助程序。
- 可导出值
// 这是数组项的 *只读* 版本
fields: Ref<FieldEntry<TValue>[]>;
// 从数组中删除指定索引处的项(如果存在)。
remove(idx: number): void;
// 替换整个字段数组。
replace(newArray: TValue[]): void;
// 更新指定索引处的值,请注意,如果值是对象,则不会合并这些值。如果指定的索引在数组边界之外,则操作将被忽略。
update(idx: number, value: TValue): void;
// 将项添加到数组的末尾
push(value: TValue): void;
// 将给定索引中的项目相互交换。这两个索引都必须存在于数组中,否则不会产生影响。
swap(indexA: number, indexB: number): void;
// 在指定索引处添加项目。如果指定的索引会将项目置于越界之外(即:大于 length),则该操作将被忽略,您仍然可以将项目添加为数组的最后一项。
insert(idx: number, value: TValue): void;
// 将项添加到数组的开头
prepend(value: TValue): void;
// 将数组项移动到数组中的其他位置。
move(oldIdx: number, newIdx: number): void;
- 应用
import { useForm, useFieldArray } from 'vee-validate';
const { handleSubmit } = useForm({
initialValues: {
links: [{ id: 1, url: 'https://github.com/logaretm' }],
},
});
const { fields, remove, replace, update, push, swap, insert, prepend, move } = useFieldArray('links');
const onSubmit = handleSubmit(values => {
console.log(JSON.stringify(values, null, 2));
});
yup
import { object, string, number, date, InferType } from 'yup';
let userSchema = object({
name: string().required(),
age: number().required().positive().integer(),
email: string().email(),
website: string().url().nullable(),
createdOn: date().default(() => new Date()),
});
pinia
创建
import { defineStore } from 'pinia'
const useStore = defineStore('storeId', {
// 推荐使用 完整类型推断的箭头函数
state: () => {
return {
// 所有这些属性都将自动推断其类型
counter: 0,
}
},
getters: {
doubleCount: (state) => state.counter * 2,
},
actions: {
increment() {
this.counter++
}
})
使用 setup()
import { useCounterStore } from '../stores/counterStore'
export default {
setup() {
const counterStore = useCounterStore()
return { counterStore }
},
computed: {
tripleCounter() {
return counterStore.counter * 3
},
},
}
不使用 setup()
import { mapState, mapWritableState } from 'pinia'
import { useCounterStore } from '../stores/counterStore'
export default {
computed: {
// 允许访问组件内部的 this.counter
// 与从 store.counter 读取相同
...mapState(useCounterStore, {
myOwnName: 'counter',
// 您还可以编写一个访问 store 的函数
double: store => store.counter * 2,
// 它可以正常读取“this”,但无法正常写入...
magicValue(store) {
return store.someGetter + this.counter + this.double
},
}),
// 允许访问组件内的 this.counter 并允许设置它
// this.counter++
// 与从 store.counter 读取相同
...mapWritableState(useCounterStore, ['counter'])
// 与上面相同,但将其注册为 this.myOwnName
...mapWritableState(useCounterStore, {
myOwnName: 'counter',
}),
},
}
使用 storeToRefs
import { useCounterStore } from '../stores/counterStore'
const store = useCounterStore();
// 通过构建新的 state 对象将 store 重置为其初始状态。
store.$reset();
// 创建一个引用对象,其中包含 store 的所有 state、getter 和插件添加的 state 属性。类似于 `toRefs(),`但专门为 Pinia 存储设计,因此方法和非响应式属性被完全忽略。
const stateGetter = storeToRefs(store);
改变状态
const store = useStore()
// 默认情况下,您可以通过 `store` 实例访问状态来直接读取和写入状态
store.counter++
// 调用 `$patch` 方法。 它允许您使用部分“state”对象同时应用多个更改
store.$patch({
counter: store.counter + 1,
name: 'Abalam',
})
// `$patch` 方法也接受一个函数来批量修改集合内部分对象的情况:
cartStore.$patch((state) => {
state.items.push({ name: 'shoes', quantity: 1 })
state.hasChanged = true
})
替换state
store.$state = { counter: 666, name: 'Paimon' }
pinia.state.value = {}
混合使用
- 新建一个文件xxxStore.ts 用于xx页面的表单操作
- 在xxx页面上导入
xxxStore.ts 其中 useForm 全局引入
import {
array, object, string,
} from 'yup';
const usexxxStore = defineStore('xxxForm', {
state: () => {
const {
validate,
values: allValues,
validateField,
setFieldValue,
resetForm,
} = useForm({
keepValuesOnUnmount: true,
validationSchema: object({
a: string().required().label('a名称'),
bList: array()
.of(
object({
c: string().required().label('c类型'),
}),
),
}),
initialValues: {
a: '',
bList: [],
},
});
const state = {
a: '',
bList: [],
};
return {
validateField,
validate,
allValues,
setFieldValue,
resetForm,
...state,
};
},
getters: {},
actions: {},
});
export default usexxxStore;
xxx.vue 其中 useFieldArray 全局引入
<script setup>
import usexxxStore from '../xxxStore';
const store = useResourceApplyStore();
const { allValues } = storeToRefs(store);
const { remove, update } = useFieldArray('bList');
</script>