Verwenden Sie TypeScript-Dekoratoren, um die Formularvalidierung und andere interessante Funktionen in Vue zu implementieren

Vorwort

Hallo zusammen, ich bin die letzte Hibana.

Typoskript-Dekoratoren sind eine sehr interessante Art zu deklarieren, durch Dekoratoren können Sie das Proxy-Muster einfach implementieren, um den Code prägnanter zu machen und einige andere interessantere Fähigkeiten zu erreichen. Wie man den Decorator und die selbst erstellte Validator-Klasse zur Implementierung der Formularvalidierung verwendet, habe ich im letzten Artikel Using TypeScript Decorators in VUE to Implement Form Validation vorgestellt. class-validatorAls Nächstes werde ich eine andere Methode zur Implementierung der Formularvalidierung verwenden.

Verwenden Sie useValidator

Bevor wir useValidator verwenden, werfen wir einen Blick darauf, wie die zuvor geschriebene Formularklasse aussieht.

class Profile {
    @IsOptional()
    avatar?: string

    @Length(2, 4, {message: '姓名长度应在2到4间'})
    realName: string

    @IsOptional()
    description?: string
}

@Reactive()
export class CreateUserForm extends Validator {
    @Length(4, 12, { message: '用户名长度应在4到12间' })
    username: string = ''

    @IsEmail({}, { message: '请填写正确的邮箱' })
    email: string = ''

    @IsMobilePhone('zh-CN', null, { message: '请输入正确的手机号码' })
    phone: string = ''

    @MinLength(4, { message: '密码长度不应低于4' })
    @MaxLength(12, { message: '密码长度不应大于12' })
    password: string = ''
 
    @Type(() => Profile)
    @ValidateNested()
    profile: Profile = new Profile()
}
复制代码

Darunter sind der @Reactive-Dekorator und die Validator-Klasse von mir gekapselt, und die anderen Formularvalidierungs-Dekoratoren verwenden class-validatorBibliotheken. Es scheint, dass es jetzt kein Problem gibt, aber wenn es viele Formulare gibt, muss jedes Formular @Reactive verwenden und die Validator-Klasse erben.Wenn es verwandte Formulare gibt und die verwandten Formulare auch die Validator-Klasse erben, wird es sehr aufgebläht .

export default defineComponent({
setup() {
    const form = new CreateUserForm()
    return  () => 
        <div>
            <field label='用户名' v-model={form.username} error={form.getError().username}></field>
            <field label='姓名' v-model={form.profile.realName} error={form.getError().profile?.realName}></field>
            <field label='邮箱' v-model={form.email} error={form.getError().email}></field>
            <field label='手机' v-model={form.phone} error={form.getError().phone}></field>
            <field label='密码' v-model={form.password} error={form.getError().password}></field>
            <button onClick={() => form.validate()}>验证</button>
            <button onClick={() => form.clearError()}>清空错误</button>
        </div> 
}})
复制代码

Das Formular von der Instanz erbt die Validator-Klasse und verfügt über Methoden wie getError und validate.

Ich hoffe, dass die Formularklasse eine sehr reine Klasse ist, nur das Formular und der Dekorateur werden für das Validierungsformular verwendet, damit die Erweiterung auch sehr bequem ist, wenn es in Zukunft andere Anforderungen gibt, und sie nach dem Vererben nicht rein sein wird die Validator-Klasse.

Danach habe ich eine useValidator-Methode implementiert, um das Formular und die damit verbundene Formularvalidierung zu unterscheiden.

export default defineComponent({
setup() {
    //往里面传入表单类,然后可以返回这些对象和方法,想用什么就解构出什么。
    const { form, errors, validateForm, clearError, toInit, toJSON } = useValidator(CreateUserForm)
    return () => (
            <div class='container'>
                <field label='用户名' v-model={form.username} error={errors.username}></field> 
                <field label='姓名' v-model={form.profile.avatar} error={errors.profile?.avatar}></field>
                <field label='邮箱' v-model={form.email} error={errors.email}></field>
                <field label='手机' v-model={form.phone} error={errors.phone}></field>
                <field label='密码' v-model={form.password} error={errors.password}></field>
                <div>
                    <button onClick={() => validateForm()}>验证</button>
                    <button onClick={() => clearError()}>取消验证</button>
                    <button onClick={() => toInit()}>初始化</button>
                </div>
            </div>
        )
}
})
复制代码

Auf diese Weise kann der von der useValidator-Methode zurückgegebene Wert jede Funktion eindeutig unterscheiden, und das Formular ist nur ein reines Formular. Dekonstruieren Sie jede gewünschte Funktion.

Natürlich ähneln die darin enthaltenen Funktionen geerbten Klassen, außer dass die eine die Methode der Klasse aufruft und die andere die von der Funktion zurückgegebene Methode verwendet. Auch ein bisschen persönliche Vorliebe.

PS: Es gibt noch einen weiteren Vorteil bei der Verwendung des Form-Decorators, der eine sehr klare Code-Eingabeaufforderung ist, wie unten gezeigt.

Tipp.gif

Wie die Formularvalidierung dieser Eigenschaft aussieht, müssen Sie nicht erst herausfinden, Sie können sie direkt auf der Eigenschaft sehen, ist das nicht sehr praktisch?

Initialwerte für Formulare dynamisch setzen

Ich habe im vorherigen Artikel erwähnt, dass der Anfangswert des Formulars dynamisch über die Schnittstelle festgelegt wird, also werde ich ihn einfach implementieren. Zum Beispiel verwende ich jetzt @InjectUsername, um den Anfangswert auf Benutzername zu setzen, und es wird einen 最后的HibanaWert namens Benutzername zurückgeben.

class CreateUserForm {
    @InjectUsername()
    @Length(4, 12, { message: '用户名长度应在4到12间'})
    username: string = ''
    //其他....
}
复制代码

Lassen Sie uns einfach den Decorator @InjectUsername implementieren.

const api = {
    //一个获取用户名的api
    getUsername() {
        return Promise.resolve('最后的Hibana')
    }
}

const InjectUsername = () => (target: any, key: string) =>
    // 定义一个叫'inject:username'的元数据,传入获取用户名api的方法
    Reflect.defineMetadata('inject', api.getUsername, target, key)

// useInject来实现将api返回的值写入到username中
function useInject<T extends object>(form: T) {
    for (const key in form) {
        const api = Reflect.getMetadata('inject', form, key)
        if (api) {
            api().then(res => {
                form[key] = res
            })
        }
    }
}
复制代码

Es ist auch sehr einfach zu bedienen, einfach useInject aufrufen, und der Benutzername kann dynamisch vergeben werden.

export default defineComponent({
setup() {
    //往里面传入表单类,然后可以返回这些对象和方法,想用什么就解构出什么。
    const { form, errors, validateForm, clearError, toInit, toJSON } = useValidator(CreateUserForm)
    useInject(form)
    return () => ( 
         <div>
             {/* ..... */} 
         </div>
        )
}
})
复制代码

Wenn Sie keine Decorators verwenden, müssen wir möglicherweise die Schnittstelle im Setup aufrufen, um Werte zuzuweisen. Nachdem Sie den Decorator verwendet haben, kann er uns helfen, diese Operationen zu verbergen.

Hinweis: Was ich hier implementiert habe, ist die einfachste Schreibweise, tatsächlich gibt es viele Details zu beachten. Zum Beispiel müssen die meisten aufgerufenen API-Schnittstellen Parameter übergeben, also wie sollen die Parameter übergeben werden?Der Dekorator der Zuweisung kann auch allgemeiner geschrieben werden; kann useInject mehr Zustände zurückgeben, wie Laden, Fehler usw ., kann es auch sein?Übergeben Sie diesen Parameter.

Typoskript-Decorator-Erweiterung

Tatsächlich können Dekorateure nicht nur für Formularklassen verwendet werden, sondern auch für Vue-Komponenten (in der Klasse geschrieben). Hier gebe ich auch kurz ein Beispiel für die mögliche Verwendung von Decorators.

class Page {
    itemList = ref([])
    //可以实现一个Watch装饰器,监听params变化
    @Watch(page => page.loadData())
    params = reactive({
        pageIndex: 1,
        pageSize: 15,
        //...
    })

    loading = ref(false)

    @Message('加载成功','获取数据失败') // 成功/错误 消息提示
    @Loading() // 自动设置loading状态
    async loadData() {
        this.itemList = await getItemList(this.params)
    }
    
    @Debounce(1000) // debounce防止多次点击
    handleLoadClick() {
        this.loadData()
    }
}
复制代码

Dann verwenden Sie es im Setup, wahrscheinlich so.

export default defineComponent({
    setup() {
        const {itemList,loading,handleLoadClick} = useInject(Page)
        // ....
    }
})
复制代码

Die Schreibweise dieser Dekorateure werde ich hier nicht umsetzen, interessierte Freunde können es selbst ausprobieren.

Ende

In diesem Artikel habe ich die useValidator-Methode zur Implementierung der Formularvalidierung sowie einige Verwendungen von Dekoratoren vorgestellt. Wie ich eingangs sagte, sind Typescript-Dekoratoren eine sehr interessante Art der Deklaration, durch die Dekorateure das Proxy-Muster einfach implementieren können, um den Code prägnanter zu machen und einige andere interessantere Fähigkeiten zu erreichen. Ich hoffe, es kann Ihr Interesse an Dekorateuren wecken.

Wenn Sie außerdem am Code zur Formularvalidierung interessiert sind, können Sie zu AndSpark/vue-class-validator (github.com) gehen .

Supongo que te gusta

Origin juejin.im/post/7077915014182469639
Recomendado
Clasificación