Maison  >  Article  >  interface Web  >  Comment implémenter le composant de validation de formulaire H5 dans vue3

Comment implémenter le composant de validation de formulaire H5 dans vue3

WBOY
WBOYavant
2023-06-03 14:09:141212parcourir

Rendu

Comment implémenter le composant de validation de formulaire H5 dans vue3

Description

Basé sur vue.js et ne repose pas sur d'autres plug-ins ou bibliothèques ; les fonctions de base restent cohérentes avec element-ui, et certaines différences mobiles ont été effectué dans la mise en œuvre interne Ajustement. vue.js,不依赖其他插件或库实现;基础功能使用保持和 element-ui 一致,内部实现做了一些移动端差异的调整。

当前构建平台使用 uni-app 官方脚手架构建,因为当下移动端大多情况就h6微信小程序两种,所以一套代码跑多端十分适合技术选型。

实现思路

核心api:使用 provide 和 inject ,对应<form></form><form-item></form-item>

  • <form></form>组件中,内部用一个变量(数组)去将所有<form-item></form-item>实例储存起来,同时把要传递的数据通过provide暴露出去;<form-item></form-item>组件则在内部用inject去接收父组件提供过来的数据,最后把自身的属性和方法提交到父组件去。

  • <form></form>中要做的事情就只有监听绑定的数据,然后做调用对应<form-item></form-item>的各种验证方法;所以任何的验证状态都写在了<form-item></form-item>中,包括样式的展示;由于可以拿到父组件绑定的数据,对于一些常见样式设置自然就可以用computed去优先拿取自身组件prop值或者父组件绑定的prop值;对应的,通过父组件绑定的表单数据,就可以和自身prop去验证当前项了,最后由父组件去调用对应方法即可,当然,自身组件也可以调用。

  • 因为vue3中移除了自定义派发事件$on$off$emit,所以这里改用uni.$onuni.$offuni.$emit来代替;不同的是,这个事件派发机制是全局的,不是跟随组件唯一性,所以在添加、移除事件时,需要在事件名称设置一个唯一值使用;这里我在<form></form>组件中定义一个变量,每次调用时都累加1,然后设为事件名称再传递到<form-item></form-item>内部,这样就可以保证<form></form><form-item></form-item>的确定性了。

与element-ui表单组件差异

  • 表单验证不再设置输入框和任何表单表单的样式,而是通过自定义修改样式去显示验证提示;这十分有利于移动端穷出不尽的UI设计稿的变化,例如同一个表单,有两种不同样式的输入框;同时不影响和其他样式库的使用,因为表单验证的<form-item></form-item>不会影响到插槽内的任何元素。

  • 表单校验数据选项只保留4个字段(见下面),因为移除了对表单组件的验证状态,所以trigger这个事件设置也不需要了;pattern则换成了reg,注意的是,在微信小程序中,任何组件的传参都会被过滤剩下基础json类型,所以这个reg在小程序环境中使用时,要在末尾加上.toString()validator同理。

/** 表单规则类型 */
export interface TheFormRulesItem {
  /** 是否必填项 */
  required?: boolean
  /** 提示字段 */
  message?: string
  /** 指定类型 */
  type?: "number" | "array"
  /**
   * 自定义的校验规则(正则)
   * - 考虑到微信一些特殊的抽风机制,在微信小程序中,除`number|string|object|undefined|null`这几个基础类型外,其他类型是会被过滤掉,所以这里在写正则的时候,在末尾加上`.toString()`即可
   */
  reg?: string // | RegExp
}

/** 表单规则类型 */
export type TheFormRules = { [key: string]: Array<TheFormRulesItem> };
  • 不知道大家在以往的长表单验证中,有没有遇到过点击验证之后,因为页面过长,所以不知道那个表单项校验不通过,从而需要翻阅定位到对应项;为了优化以往表单验证的体验,这里加入了验证之后,滚动到对应位置的操作,更加符合移动端的用户体验。

  • 表单验证的触发机制:都知道element-ui的触发机制是通过指定trigger来选择触发的时机,那这里我去掉之后,就意味着没有这些操作去触发了;而我选择的是主动调用validatevalidateField这些验证方法时去触发实时验证,当验证不通过时,把不通过的用变量储存起来,然后每次数据变动时去校验,等到验证通过了,则移除实时验证项;这样相比于element-ui

    La plate-forme de construction actuelle est construite à l'aide de l'échafaudage officiel uni-app. Parce que la plupart des terminaux mobiles ont actuellement deux types : h6 et Applet WeChat, elle est donc très adaptée. un ensemble de codes à exécuter sur plusieurs terminaux. 🎜🎜Idée d'implémentation🎜🎜API principale : utilisez provide et inject, correspondant à <form></form> et <form-item></form-item>. 🎜
    • 🎜Dans le composant <form></form>, une variable (tableau) est utilisée en interne pour combiner tous les <form- item>L'instance est stockée et les données à transférer sont exposées via <code>provide ; le composant <form-item></form-item> utilise inject pour recevoir les données fournies par le composant parent, et enfin soumettre ses propres propriétés et méthodes au composant parent. 🎜
    • 🎜<form></form> Il suffit d'écouter les données liées puis d'appeler le <form-item></form-item>correspondant > Diverses méthodes de vérification ; donc tout statut de vérification est écrit en <form-item></form-item>, y compris l'affichage des styles puisque les données liées au composant parent peuvent être obtenues, pour certains styles courants, bien sûr ; vous pouvez utiliser calculed pour obtenir la valeur prop de son propre composant ou la valeur prop liée au composant parent en conséquence, via le composant parent ; Les données du formulaire lié peuvent être utilisées avec son propre prop pour vérifier l'élément actuel. Enfin, le composant parent peut appeler la méthode correspondante. Bien entendu, son propre composant peut également l'appeler. 🎜
    • 🎜Parce que les événements de répartition personnalisés $on, $off et $ ont été supprimés de <code>vue3 émettre, donc ici nous utilisons uni.$on, uni.$off et uni.$emit à la place différents Oui ; , ce mécanisme de répartition des événements est global et ne suit pas le caractère unique du composant, donc lors de l'ajout ou de la suppression d'événements, vous devez définir une valeur unique dans le nom de l'événement ; ici, j'utilise le <form> code> Composant Définissez une variable dans <code>1 à chaque fois qu'elle est appelée, puis définissez-la comme nom d'événement et transmettez-la à l'intérieur de <form-item></form-item>, ainsi que <form></form> et <form-item></form-item> sont certains. 🎜
    🎜Différences par rapport aux composants de formulaire element-ui🎜
    • 🎜La validation de formulaire ne définit plus le style de la zone de saisie et de tout formulaire de formulaire ; Afficher les invites de vérification en personnalisant le style ; cela est très propice aux changements sans fin dans le projet de conception de l'interface utilisateur sur le terminal mobile, par exemple, le même formulaire a deux styles différents de zones de saisie en même temps ; temps, cela n'affecte pas l'utilisation d'autres bibliothèques de styles, car la validation du formulaire <form-item></form-item> n'affectera aucun élément de l'emplacement. 🎜
    • 🎜L'option de données de validation du formulaire ne conserve que les champs 4 (voir ci-dessous), car le statut de validation du composant du formulaire est supprimé, donc déclencheur Ce paramètre d'événement n'est plus nécessaire ; pattern est remplacé par reg. Notez que dans l'applet WeChat, les paramètres transmis par n'importe quel composant seront filtrés et laissés de côté. code>json, donc lorsque ce reg est utilisé dans un environnement de mini-programme, .toString() et validator doivent être ajoutés à la fin De même. 🎜
    function moduleEvent() {
      /** 
      * 事件集合对象
      * @type {{[key: string]: Array<Function>}}
      */
      const eventInfo = {};
    
      return {
        /**
         * 添加事件
         * @param {string} name 事件名
         * @param {Function} fn 事件执行的函数
         */
        on(name, fn) {
          if (!eventInfo.hasOwnProperty(name)) {
            eventInfo[name] = [];
          }
          if (!eventInfo[name].some(item => item === fn)) {
            eventInfo[name].push(fn);
          }
        },
    
        /**
         * 解绑事件
         * @param {string} name 事件名
         * @param {Function} fn 事件绑定的函数
         */
        off(name, fn) {
          const fns = eventInfo[name];
          if (fns && fns.length > 0 && fn) {
            for (let i = 0; i < fns.length; i++) {
              const item = fns[i];
              if (item === fn) {
                fns.splice(i, 1);
                break;
              }
            }
          } else {
            console.log("[moduleEvent] => 没有要解绑的事件");
          }
        },
    
        /**
         * 调用事件
         * @param {string} name 事件名
         * @param {any} params 事件携带参数
         */
        dispatch(name, params) {
          const fns = eventInfo[name];
          if (fns && fns.length > 0) {
            for (let i = 0; i < fns.length; i++) {
              const fn = fns[i];
              fn(params);
            }
          } else {
            console.log("[moduleEvent] => 没有要执行的事件");
          }
        },
      }
    }
    • 🎜Je ne sais pas si vous avez déjà rencontré la page après avoir cliqué sur la vérification lors de la dernière vérification longue durée, car le la page est trop longue, donc je ne sais pas quel élément du formulaire a échoué à la vérification, je dois donc parcourir pour localiser l'élément correspondant afin d'optimiser l'expérience de la vérification du formulaire précédent, l'opération de défilement jusqu'à la position correspondante après ; une vérification est ajoutée ici, ce qui est plus conforme à l'expérience utilisateur du terminal mobile. 🎜
    • 🎜Mécanisme de déclenchement de la vérification du formulaire : Nous savons tous que le mécanisme de déclenchement de element-ui consiste à sélectionner l'heure de déclenchement en spécifiant trigger, donc ici, après l'avoir supprimé, cela signifie qu'il n'y a pas ces opérations à déclencher ; et ce que j'ai choisi, c'est d'appeler activement les méthodes de vérification validate et validateField pour déclencher de vrais- vérification temporelle. Lorsque la vérification échoue, lorsque la vérification est réussie, ceux qui ont échoué sont stockés dans des variables, puis vérifiés à chaque fois que les données changent. Lorsque la vérification est réussie, les éléments de vérification en temps réel sont supprimés de cette manière, par rapport aux événements de liaison element-ui La vérification en temps réel permettra d'économiser beaucoup de mécanismes d'appel et d'exécution de code, et le code peut être plus sophistiqué et rationalisé. 🎜

    非uni-app平台的移植

    除了更换标签之外,几乎不用做任何的修改就可以复制粘贴到其他项目中去,唯一要修改的就是自定义事件uni.$onuni.$offuni.$emit;这里可以自己实现,又或者用其他库去代替,js实现自定义事件派发代码如下:

    function moduleEvent() {
      /** 
      * 事件集合对象
      * @type {{[key: string]: Array<Function>}}
      */
      const eventInfo = {};
    
      return {
        /**
         * 添加事件
         * @param {string} name 事件名
         * @param {Function} fn 事件执行的函数
         */
        on(name, fn) {
          if (!eventInfo.hasOwnProperty(name)) {
            eventInfo[name] = [];
          }
          if (!eventInfo[name].some(item => item === fn)) {
            eventInfo[name].push(fn);
          }
        },
    
        /**
         * 解绑事件
         * @param {string} name 事件名
         * @param {Function} fn 事件绑定的函数
         */
        off(name, fn) {
          const fns = eventInfo[name];
          if (fns && fns.length > 0 && fn) {
            for (let i = 0; i < fns.length; i++) {
              const item = fns[i];
              if (item === fn) {
                fns.splice(i, 1);
                break;
              }
            }
          } else {
            console.log("[moduleEvent] => 没有要解绑的事件");
          }
        },
    
        /**
         * 调用事件
         * @param {string} name 事件名
         * @param {any} params 事件携带参数
         */
        dispatch(name, params) {
          const fns = eventInfo[name];
          if (fns && fns.length > 0) {
            for (let i = 0; i < fns.length; i++) {
              const fn = fns[i];
              fn(params);
            }
          } else {
            console.log("[moduleEvent] => 没有要执行的事件");
          }
        },
      }
    }

    调用moduleEvent()之后,用变量调用即可,注意当前变量要作为内存常驻使用。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer