During this period, I was in the preliminary construction of a new project. The framework of the new project was built with VUE-CLI3 and typescirpt. Because the project was lightweight, I didn’t use any extra UI components, and sometimes I just developed the basic components we needed. Today we’ll show you how to use vue’s custom directive to develop a form validation plug-in. This article is based on TS development, if students need JS version of the TS syntax to JS can be.

1. Vue plug-in development

Plugin development for Vue is clearly explained in the official documentation. For details, please read the development documentation. Validate.ts, the form validation plug-in developed this time, takes advantage of this approach.

  • Vue global directive
// myPlugin.js
export default {
  install: (Vue, options) = > {
    // Register a my-directive
    Vue.directive('my-directive', {
      bind(el, binding, vnode, oldVnode) {
        / / logic}... }}})// main.js
import Vue from 'vue';
import myPlugin from 'myPlugin';
Vue.use(myPlugin);

Copy the code

Bind () is the hook function of the directive. The parameter EL represents the element to which the directive is bound. DOM manipulation can be performed directly. Binding is an object that contains the instruction name, binding value, and other information. Vnode and oldVnode represent virtual nodes generated by Vue compilation.

We validate the current input value by registering a global directive, v-validateParams, bound to the input tag of the input form.

2. V – validateParams instructions

At first, I referred to some code on the Internet, and the idea was as follows:

  • The overall train of thought
import Vue from 'vue'
export default {
  install: (Vue, options) = > {
    // Register a global custom directive 'V-validateParams'
    Vue.directive('validateParams', {
      // When the bound element is inserted into the DOM
      inserted: function (el, binding, vNode) {
        // Add an event listener to the Dom element bound to the instruction to detect out-of-focus events in the input box
        The function is executed each time the input field in the form is out of focus
        el.addEventListener('blur'.function (event) {
          // 1. Reset all error messages first
          // 2. Get the validation rule parameters and form input values passed in the custom directive
          // 3. Check whether the entered value complies with verification rules})}})// Register a global custom directive 'V-validatesubmit' that is bound to the form submission button
    Vue.directive('validateSubmit', {
      // When the bound element is inserted into the DOM
      inserted: function (el, binding, vNode) {
        // Add event listener to submit button
        el.addEventListener('click'.function (event) {
          // Get all elements in the current component that contain the v-check class name
          let elements = vNode.context.$el.getElementsByClassName('v-check')
          var evObj = vNode.context.$el.createEvent('Event')
          evObj.initEvent('blur'.true.true)
          for (let element of elements) {
            // Bind the blur event to all v-check elements
            element.dispatchEvent(evObj);
          }
          // Get all error elements under the current component
          let errorInputs = vNode.context.$el.getElementsByClassName('input-error');
          // If there are no error elements in the component, the submit() function in the current component instance is executed
          if(errorInputs.length === 0){ vNode.context.submit(); }})}})}Copy the code

A few words about the validateSubmit directive, which binds to the submit button and validates when clicked, and commits when verified. But the implementation here is not particularly friendly:

  1. You need to get all the input elements in the current component, bind them, and execute themblurEvent to executevalidateParamsCheck logic in instruction.
  2. Gets all error elements in the current component. If they are present, they are not validated and cannot be continued.
  3. If the component does not contain any error message, the verification succeedssubmitFunction, so each form component’s submission function can only be namedsubmit

Let’s take a look at the internal implementation of the directive validateParams. This directive needs to bind to the form input element and pass in the validation rule as an argument. When the input element is out of focus, the logic in the event that binds the current element in the directive is executed. This logic is divided into three steps, which I have written down in the comments. Now let’s look at the implementation.

  • Reset all error messages
/** * resets the current node style * @param el: HTMLElement, passing in the currently bound input element */
const resetError = (el: HTMLElement) = > {
  el.className = el.className.replace('input-error'.' ').trim();
  if ( el.parentNode ) {
    const ErrorNode = el.parentNode.querySelector('.error-tips');
    if(ErrorNode) { el.parentNode.removeChild(ErrorNode); }}};Copy the code
  • Gets the validation rule parameter and form input values passed in the custom directive
// Binding. value is an array of arguments passed to the custom directive
for (const rule of binding.value) {
  // Obtain their own verification rules and execute them
  const { min, max, message, required, pattern } = rule;
  if(!!!!! required && ! InputEl.value ) {// If not, execute the error function
    validateError(InputEl, message);
    break;
  }
  if ( min && InputEl.value.length < min ) {
    validateError(InputEl, message);
    break;
  }
  if ( max && InputEl.value.length > max ) {
    validateError(InputEl, message);
    break;
  }
  if( pattern && ! pattern.test(InputEl.value) ) { validateError(InputEl, message);break;
  }
  if ( rule && typeof rule === 'function' ) {
    rule(vNode.context, InputEl.value, validateError, InputEl);
    break; }}Copy the code
  • If the check does not match, execute the error function
@param el: HTMLElement, pass in the currently bound input element * @param errorMsg: String, an error message is passed in */
const validateError = (el: HTMLElement, errorMsg: string) = > {
  if (Array.prototype.includes.call(el.classList, 'input-error')) {
    // If the current component already has an error message, do nothing
    return;
  } else {
    const errorNode = document.createElement('p');
    errorNode.className = 'error-tips';
    errorNode.textContent = errorMsg;
    if (el.parentNode) {
      // Append a p element to the current input element with an error message
      el.parentNode.appendChild(errorNode);
    }
    // Add an input-error class name to the current input element
    el.className += ' input-error'; }};Copy the code

Now I put their implementation of this form verification plug-in roughly said, let’s see the specific use.

3. Use of form plug-ins

First create a verification rule file:

// rules.ts export const required = (message) => ({ message, required: true }); export const min = (message, length=3) => ({ message, min: length }) export const max = (message, length=15) => ({ message, max: length }) export const pattern = (message, reg) => ({ message, pattern: Reg}) // form.vue <template> <div> <div class="form-item"> <label for="userEmail"> </label> <input id="userEmail" class='v-check' type="text" v-model="userName" v-validateParams="[inputNameRequired, inputNameMin, inputNameMax, InputNamePattern "> </div> <button class=" BTN "type="success" V-checkSubmit > confirm </button> </div> </template> <script lang='ts'> import { Component, Vue, Prop } from 'vue-property-decorator'; import { max, min, required, name, pattern} from 'rules'; @Component({}) export default class Auth extends Vue { private userName: string = ''; Private inputNameMax = Max (' please do not exceed 20 characters '); Private inputNameMin = min(' please do not less than 3 characters '); Private inputNameRequired = Required (' Please enter username '); Private inputNamePattern = pattern(' please enter a correct user name ', /^[a-za-z0-9_ -]{4,16}$/); Private submit() {alert(' pass '); } } </script>Copy the code

From this example we can see that validation rules need to be introduced and assigned to the data in the VUE instance. Then in the template, you need to add the V-Check class name to the input tag, use the V-validateParams directive, and pass in the parameters. The submit button calls the V-CheckSubmit directive. In this way, you can use the form you developed to validate the plug-in.

3. Problems existing in the current mode

Although form validation is available, there are some obvious problems:

  1. Js and HTML are highly coupled, the plug-in also needs to obtain DOM elements, and the component’s HTML template also needs to add the specified class name.
  2. Using DOM manipulation in VUE is not in line with vUE’s design ideas and implementation is not elegant.
  3. The validation logic of the validation rule is written when the directive is defined. Adding or deleting a validation rule requires modification of the plug-in code.
  4. The commit directive determines the current validation state based on whether the current component contains a specific DOM, and the name of the function to perform the commit is specified in the instruction logic.

I realized this form verification plug-in based on an existing demo combined with my own requirements. In the development process, I already knew that there were many problems in writing this way, and I also clearly realized that my javascript level was still very elementary, and I needed to continue to study hard.

The main problem with the current form plug-in development is how to return the validation state in the plug-in to the component. We can maintain an event handler within the plug-in that passes in validation rules and validates them, and then passes the validation results directly to the component. This avoids a lot of DOM manipulation. After that, I need to refactor the plugin as quickly as possible.

Subsequent update: Optimized the form plug-in

Refer to the article

Vue plug-in

Vue custom command

Vue implements form validation using custom directives

Refactoring: Build a Vue form validation plug-in from 0.1

Va.js — The writing process of Vue form validation plug-in


About the author: Gong Chenguang,And in the futureBig data front-end engineer.