vuecomponent / use Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
这个例子中展示了如何使用自定义验证规则来完成密码的二次验证。本例还使用 has-feedback 属性为输入框添加了表示校验结果的反馈图标。
自定义校验 callback 必须被调用
我看useForm好像没有能验证二次密码的东西
We have been working on the decoupling and ease of use of Form components, and now we have designed a new way of using them through composition-api. Don't worry, the old way of using will always be supported. Now you can view the examples on the official website and give us suggestions.
useForm provides functions through a separate module, welcome star it.
you can star it. https://github.com/vueComponent/use
我们一直在致力于Form组件的解耦和易用,现在我们通过 composition-api 设计了全新的使用方式。不用担心,现有的使用方式也会一直支持。现在你可以通过官网查看示例,给我们提建议。
useForm 通过一个独立的模块提供功能,欢迎 star。
https://github.com/vueComponent/use
在微信公众号上看到您的文章, 很兴奋, 对于您提出的这个问题, 我也思考过很多, 除了您提出并实践的分离转态之外, 还有接口继承体系以及ui代码自动生成需要完善, 这些都做了才能服务于下一代组件基础设施. 下面是我的详细论述, 但是这些都不重要, 重要的是我想加您的微信, 详细聊一下 ^-^
现状: 当前的web组件, 复用的基本单元为组件(类), 试图将所有需要的功能都封装在组件中, 并通过配置项的方式提供出来, 以方便使用者使用. 这种方式有以下三个主要问题:
将具体实现与对外标准分离的web组件库编程技术, 制定了一套面向使用者的标准. 使用者只需关注标准, 具体的组件实现遵守该标准. 带来的好处:
以业界目前知名的组件库 AntdDesign 为例子
该组件库, 组织组件的基本单元是具体实现, 基本每种组件只提供了一个具体实现, 并提供了详细的 api 说明文档, 却并未定义对外标准. 随着组件库的升级, 功能的增加, 增加了越来越多的 api 配置项, 来满足不同的业务需求.
缺点:
1. 复用的基本单元是具体组件实现, 随着功能的增加, 具体组件变成了一个巨石组件, 体积越来越大, 极难维护, 且难以使用.
2. 为了满足不同的业务需求, 为单个组件增加了很多逻辑, 并通过 api 配置项对用户透出, 虽然增加的配置项都有默认值, 如果不使用对应的功能可以不关注. 但是这种通过扩充配置项的方式破坏了组件的通用性,
特别是当前 lowCode, 搭建系统, schemaToPage, 智能化等基于基础组件库的提效系统大发展的今天. 这些上层系统没有一个通用的组件库标准可以依赖, 只能依赖具体的组件, 导致上层系统与基础组件库强绑定, 使其难以成为成长为业界通用的方案.
3. 如果开发者有个性的话的需求, 由于现有组件库基本未考虑过扩展性问题, 导致很难扩展, 基本就只能改改样式, 如果想要增加个性化功能, 基本只能自己从零开始实现一个新的, 成本很高.
4. 随着功能的增加, "个性化"化的配置越来越多, 导致使用者的迁移成本及其高, 如果转换使用另外一套组件库, 又要重新学习另外一套个性化配置.
单个组件架构
如图1所示: 使用者只依赖于组件统一标准, 同时组件统一标准, 有可能会有很多具体实现. 比如 具体组件(默认提供), 这就是一个默认提供的组件. 如果使用者有一些个性化需求, 那么可以通过已有的通用逻辑, 当然也可以自己添加个性化的逻辑再加上个性化的 html + css 来实现个性化组件, 同时 由于个性化组件也是实现了组件统一标准, 所以对于使用者来说是无感知的, 低成本的.
一个更加通用的场景
图2 是一个省略设计细节的关系图, 从上图可以很清楚的看出, 上层提效系统依赖的只是通用对外标准, 任何实现了通用标准的组件库都可以容易的接入上层提效系统.
从上图可以看出上层应用不直接依赖具体实现, 而是依赖通用接口, 上层依赖可根据自己系统的需要依赖某个标准或者是标准的组合, 任何实现了某个系统依赖的标准或标准组合的组件都可以以很低成本被这个系统使用.
通用接口层, 为了保证标准的灵活性, 标准是由多多层继承关系组织的, 另外还有一些相对独立的标准, 比如受控组件标准, 或可以disable 标准等.
具体组件库可根据业务需求选择实现其中的某个或几个标准.
具体实现可以选择继承基础按钮组件, 以实现复用基础代码
请问可以提取 useForm 返回的类型并导出吗
继承类时需要重写该属性 该方法没有抽离类型并导出 目前需要自行复制类型解决
import { useForm } from '@ant-design-vue/use';
Currently some functions does not support generics so we cannot leverage the power of typescript on returning data.
Take for example this one --> https://2x.antdv.com/components/form/#components-form-demo-useform
I have an interface
interface User {
email: string
firstName: string
lastName: string
}
I want to control the validation to return that type
const data = await validate<User>()
So I am sure that the validate function just return the correct type.
Looking in the generated type files I see
declare function useForm(modelRef: Props, rulesRef?: Props, options?: {
immediate?: boolean;
deep?: boolean;
validateOnRuleChange?: boolean;
debounce?: DebounceSettings;
}): {
modelRef: Props;
rulesRef: Props;
initialModel: Props;
validateInfos: validateInfos;
resetFields: () => void;
validate: (names?: string | string[], option?: validateOptions) => Promise<any>;
validateField: (name?: string, value?: any, rules?: [Record<string, unknown>], option?: validateOptions) => Promise<any>;
mergeValidateInfo: (items: validateInfo | validateInfo[]) => validateInfo;
};
Where validate
and validateField
are set to Promise<any>
instead of some thing like
validate: (names?: string | string[], option?: validateOptions)<T = any> => Promise<T>;
validateField: (name?: string, value?: any, rules?: [Record<string, unknown>], option?: validateOptions)<T = any> => Promise<T>;
ERROR Failed to compile with 2 errors 11:45:01 AM
error in ./node_modules/@ant-design-vue/use/es/useEventListener/index.js
Module parse failed: Unexpected token (13:20)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| var prevEle = null;
| var destroyWatcher = watchEffect(function () {
> bindEle.value?.addEventListener(type, listener, options);
|
| if (prevEle) {
@ ./node_modules/@ant-design-vue/use/es/index.js 6:0-65 6:0-65
@ ./node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/ts-loader??ref--14-2!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader-v16/dist??ref--0-1!./src/views/Login.vue?vue&type=script&lang=ts
@ ./src/views/Login.vue?vue&type=script&lang=ts
@ ./src/views/Login.vue
@ ./src/router/index.ts
@ ./src/main.ts
@ multi (webpack)-dev-server/client?http://172.16.1.169:8080&sockPath=/sockjs-node (webpack)/hot/dev-server.js ./src/main.ts
error in ./node_modules/@ant-design-vue/use/es/useForm/index.js
Module parse failed: Unexpected token (250:14)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| var arg = infos[i];
|
> if (arg?.validateStatus === 'error') {
| info.validateStatus = 'error';
| arg.help && help.push(arg.help);
@ ./node_modules/@ant-design-vue/use/es/index.js 1:0-47 1:0-47
@ ./node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/ts-loader??ref--14-2!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader-v16/dist??ref--0-1!./src/views/Login.vue?vue&type=script&lang=ts
@ ./src/views/Login.vue?vue&type=script&lang=ts
@ ./src/views/Login.vue
@ ./src/router/index.ts
@ ./src/main.ts
@ multi (webpack)-dev-server/client?http://172.16.1.169:8080&sockPath=/sockjs-node (webpack)/hot/dev-server.js ./src/main.ts
import { defineComponent, reactive } from 'vue';
import { useForm } from '@ant-design-vue/use';
interface Form {
username: string;
password: string;
}
export default defineComponent({
setup () {
const formData: Form = reactive({
username: '',
password: ''
});
const validateRules = reactive({
username: [{
required: true,
message: '请输入用户名'
}],
password: [{
required: true,
message: '请输入密码'
}]
});
const { resetFields, validate, validateInfos } = useForm(formData, validateRules);
const onSubmit = (e: Event) => {
e.preventDefault();
validate().then(res => {
console.log(res);
}).catch(err => {
console.log(err);
});
};
const onReset = () => {
resetFields();
};
return {
labelCol: { span: 4 },
wrapperCol: { span: 10 },
formData,
validateInfos,
onSubmit,
onReset
};
}
});
2.0.0-rc.4
Vue3
https://codesandbox.io/s/practical-driscoll-ysu15?file=/src/App.vue
填写表单所有必填字段后,点击提交按钮执行 validate 进行校验,界面无警告,控制台也无警告,但是validate会走catch
能正常通过校验
所有必填字段都有值,且无任何警告,但是validate会跳到catch
Version
vue: 3.0.4
antdv: 2.0.0-rc.5
antdv/use: 0.0.1-alpha.8
Environment
Vue3
Reproduction link
https://codesandbox.io/s/vue3-antdv2x-menu-recursion-forked-iue1c?file=/src/App.vue
Steps to reproduce
见上面的连接
What is expected?
在不传递rules 给useForm时,能正常渲染并使用
What is actually happening?
不传递rules时就会报错且页面无法渲染
import { useForm } from '@ant-design-vue/use';
const { validate, resetFields } = useForm(formModel);
报错信息
Uncaught (in promise) TypeError: Cannot convert undefined or null to object
at Function.keys ()
at useForm (index.js?084c:103)
回显表单数据的时候,再次验证表单会出错
2.0.0-rc.4
MacOS 11.1 / Windows 21H1,Chrome87,Vue 3.0.4,ant-design-vue 2.0.0-rc5
<template>
<h1>vite app</h1>
</template>
<script lang="ts">
import { defineComponent, reactive } from 'vue'
import { useForm } from '@ant-design-vue/use'
export default defineComponent({
name: 'App',
setup() {
const modelRef = reactive({})
const rulesRef = reactive({})
const { validate, validateInfos } = useForm(modelRef, rulesRef)
return {
validate,
validateInfos
}
}
})
</script>
控制台报错:Uncaught SyntaxError: The requested module '/@modules/@babel/runtime/regenerator/index.js' does not provide an export named 'default'
控制台报错:Uncaught SyntaxError: The requested module '/@modules/@babel/runtime/regenerator/index.js' does not provide an export named 'default'
vite 提示
[vite] Avoid deep import "ant-design-vue/es/form/utils/validateUtil" (imported by /@modules/@ant-design-vue/use/es/useForm/index.js)
because "ant-design-vue" has been pre-optimized by vite into a single file.
Prefer importing directly from the module entry:
import { ... } from "ant-design-vue"
If the dependency requires deep import to function properly,
add the deep path to optimizeDeps.include in vite.config.js.
2.0.0-beta.12
vue: 3.0.2
<Form>
<Form.Item label="用户名" required {...validateInfos.username}>
{/* <Form.Item label="用户名" required> */}
<Input type="text" v-slots={{ prefix: iconUser }} v-model={[modelRef.username, 'value']} />
</Form.Item>
</Form>
错误信息:
Type '{ autoLink?: boolean | undefined; required: boolean; validateStatus?: "error" | "success" | "validating" | null | undefined; help?: string | undefined; label: string; }' is not assignable to type 'IntrinsicAttributes & Partial<{ prefixCls: string; id: string; htmlFor: string; hasFeedback: boolean; autoLink: boolean; }> & Pick<Readonly<{ prefixCls: string; id: string; htmlFor: string; hasFeedback: boolean; autoLink: boolean; } & { ...; }> & VNodeProps & AllowedComponentProps & ComponentCustomProps, "label" | ....'.
Type '{ autoLink?: boolean | undefined; required: boolean; validateStatus?: "error" | "success" | "validating" | null | undefined; help?: string | undefined; label: string; }' is not assignable to type 'Pick<Readonly<{ prefixCls: string; id: string; htmlFor: string; hasFeedback: boolean; autoLink: boolean; } & { label?: VueNode; name?: string | number | string[] | number[] | undefined; help?: VueNode; ... 11 more ...; messageVariables?: Record<...> | undefined; }> & VNodeProps & AllowedComponentProps & ComponentCus...'.
Types of property 'validateStatus' are incompatible.
Type '"error" | "success" | "validating" | null | undefined' is not assignable to type '"" | "error" | "success" | "warning" | "validating" | undefined'.
Type 'null' is not assignable to type '"" | "error" | "success" | "warning" | "validating" | undefined'.
27 | <div class="login-box">
28 | <Form layout="vertical">
> 29 | <Form.Item label="用户名" required {...validateInfos.username}>
通过编译,去除错误。
Types of property 'validateStatus' are incompatible.
tsx
ant-design-vue 2.0.0-beta.10
@ant-design-vue/use: "0.0.1-alpha.6",
vue 3.0.0-0
// login.tsx
setup(){
const model=reactive({username:"",password:""})
const rules=reactive({
username:[{required:true,message:"请输入用户名"}]
})
const form=useForm(model,rules)
return ()=><Form>
<Form.Item {...form.validateInfos.username}>
</Form.Item>
</Form>
}
不能将类型“{ autoLink?: boolean | undefined; required?: boolean | undefined; validateStatus?: "validating" | "error" | "success" | null | undefined; help?: string | undefined; }”分配给类型“IntrinsicAttributes & HTMLAttributes & { colon?: boolean | undefined; extra?: string | number | boolean | void | Element | VNode<RendererNode, RendererElement, { ...; }> | VNodeArrayChildren | null | undefined; ... 13 more ...; validateTrigger?: string | ... 2 more ... | undefined; }”。
不能将类型“{ autoLink?: boolean | undefined; required?: boolean | undefined; validateStatus?: "validating" | "error" | "success" | null | undefined; help?: string | undefined; }”分配给类型“{ colon?: boolean | undefined; extra?: string | number | boolean | void | Element | VNode<RendererNode, RendererElement, { [key: string]: any; }> | VNodeArrayChildren | null | undefined; ... 13 more ...; validateTrigger?: string | ... 2 more ... | undefined; }”。
属性“validateStatus”的类型不兼容。
不能将类型“"validating" | "error" | "success" | null | undefined”分配给类型“"" | "validating" | "error" | "success" | "warning" | undefined”。
不能将类型“null”分配给类型“"" | "validating" | "error" | "success" | "warning" | undefined”。ts(2322)
declare function useForm(modelRef: Props, rulesRef?: Props, options?: {
immediate?: boolean;
deep?: boolean;
validateOnRuleChange?: boolean;
debounce?: DebounceSettings;
}): {
.......
};
function useForm(modelRef, rulesRef, options) {
var initialModel = cloneDeep(modelRef);
var validateInfos = {};
Object.keys(rulesRef).forEach(function (key) {
validateInfos[key] = {
autoLink: false,
required: isRequired(rulesRef[key])
};
});
......
}
rulesRef为非必填参数,但是useForm方法中,却没有判断rulesRef是否为undefined,直接进行Object.keys操作....这样会报错~
目前有解决办法
useForm(modelRef, reactive({}));
rulesRef必须为reactive对象,直接使用空对象会有警告,这是由于
watch(rulesRef, function () {
if (options && options.validateOnRuleChange) {
validate();
}
}, {
deep: true
})
这一段代码导致,所以watch必须是一个reactive对象,
<a-form v-bind="layout" layout="horizontal">
<a-form-item v-bind="validateInfos.menuId" label="所属菜单">
<a-tree-select
v-model:value="modelRef.menuId"
:treeData="menuTreeData"
:replaceFields="{ children: 'children', label: 'menuName', value: 'id', key: 'id' }"
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
placeholder="请选择所属菜单"
@change="handleMenuTreeSelectChange"
></a-tree-select>
</a-form-item>
<a-form-item label="菜单编码">
<a-input v-model:value="modelRef.menuCode" disabled></a-input>
</a-form-item>
<a-form-item v-bind="validateInfos.buttonName" label="按钮名称">
<a-input v-model:value="modelRef.buttonName" placeholder="请输入按钮名称"></a-input>
</a-form-item>
<a-form-item v-bind="validateInfos.buttonKey" label="按钮标识">
<a-input v-model:value="modelRef.buttonKey" placeholder="请输入按钮标识"></a-input>
</a-form-item>
</a-form>
const rulesRef = reactive({
menuId: [{ required: true, message: '必填项', trigger: 'change' }],
buttonKey: [{ required: true, message: '必填项', trigger: 'blur' }],
buttonName: [{ required: true, message: '必填项', trigger: 'blur' }],
});
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.