Vue 3 custom instruction development

What is directive
Both Angular and Vue have the concept of Directive. We usually translate Directive into "instruction".

In computer technology, an instruction is a single CPU operation defined by the instruction set architecture. In a broader sense, "instruction" can be a representation of any element of an executable program, such as bytecode.

So what is the "instruction" in the front-end framework Vue and what is its role?

In Vue development, we often use keywords starting with V - such as v-model and v-show in the template. These keywords are the built-in instructions of Vue framework. By using v-model, you can obtain and implement the binding between Dom and data; Using v-show, you can control the display of DOM elements. In short, by using the tags on these templates, the framework performs the specified processing on DOM elements, and the framework can update the specified data at the same time after DOM changes. Instruction is one of the foundations of Vue MVVM.

Usage scenario of instruction

In addition to using built-in instructions, Vue also supports user-defined instructions. The following scenarios can be realized through user-defined instructions:

The basic operation of DOM. When some processing in the component cannot be implemented with existing instructions, you can customize the instruction implementation. For example, component watermark, auto focus. Compared with obtaining DOM operations with ref, the encapsulated instructions are more in line with the architecture of MVVM, and M and V do not interact directly.

< p v-highlight="'yellow'">Highlight this text bright yellow p >

 

The common operations available for multiple components can be reused through the use of components. Similarly, the reuse of functions on components can also be realized through the use of components. For example, spell check, picture lazy loading. Using components, as long as you label the input components that need spell checking, you can inject the spell checking function into the components all the time. There is no need to package new spelling support functions for different components.

Vue 3 how to customize instructions
Vue supports global registration and local registration instructions.

Global registration is registered through the direct method of the app instance.

let app = createApp(App)

app.directive('highlight', {

beforeMount(el, binding, vnode) {

el.style.background = binding.value

}

})

Local registration is registered by setting the directive property to the component

export default defineComponent({

name: "WebDesigner",

components: {

Designer,

},

directives: {

highlight: {

beforeMount(el, binding, vnode) {

el.style.background = binding.value;

},

},

},

});

The registered component contains the name of the component. It needs to be unique and an implementation object of the component. After being registered, it can be used on any element.  

1

< p v-highlight="'yellow'">Highlight this text bright yellow p >

A custom component is to implement the hook function provided by Vue. In Vue 3, the life cycle of the hook function is similar to that of the component:

Created - called after the element is created, but the attributes and events have not yet taken effect.
beforeMount - called only once when the instruction binds the element for the first time.
mounted - called when the element is inserted into the parent element
beforeUpdate: calls before the element updates itself.
Updated - element or sub - element is updated after it is called.
beforeUnmount: element is called before unloading.
unmounted - when the instruction is unloaded, it will be called only once.
Each hook function has the following parameters:

el: the element bound by the instruction, which can be used to directly operate the DOM
The following objects contain data: binding

instance: The instance of the current component. Generally, the recommended instruction is independent of the component. If necessary, use the component context ViewModel,You can get it here
value: The value of the instruction, that is, the value in the above example“ yellow"
oldValue: The previous value of the instruction, in beforeUpdate and Updated In, can and value Is the same content.
arg: Parameters passed to the instruction, such as v-on:click Medium click. 
modifiers: The object that contains the modifier. for example v-on.stop:click You can get one{stop:true}Object of

Vnode: virtual node generated by Vue compilation,
Prevvnode: the last virtual node at update time

Vue 2 instruction upgrade
The instruction is a Breaking Change in vue3. The name and number of hook functions of the instruction have changed. Vue3 creates more functions for instructions. The function name is consistent with the life cycle of components and is easier to understand.

The following is an introduction to the changes

Another change is that the acquisition method of component context objects has changed. Generally recommended game Instructions and component instances are independent of each other. Accessing component instances from within custom instructions may indicate that there is no need to encapsulate instructions here. Instructions are the functions of component capabilities. However, it is possible that some scenarios need to obtain component instances.

In Vue 2, it is obtained through the vnode parameter

bind(el, binding, vnode) {

        const vm = vnode.context        

}

 

In Vue 3, it is obtained through the binding parameter

mounted(el, binding, vnode) {

        const vm = binding.instance        

}

Vue 3 custom instruction instance – input spell check
Use pluginwww sangpi. Com.

Create a new spellcheckplugin TS, declare the plug-in and inject instructions into the install method of the plug-in

import { App } from 'vue'

function SpellCheckMain(app: App, options: any) {

//

}

export default {

          install: SpellCheckMain        

}

SpellCheckMain method implements components and spell checking methods. Specific spell checking rules can be implemented according to business or using other plug-in methods

function SpellCheckMain(app: App, options: any) {

          const SpellCheckAttribute = "spell-check-el";        



          let SpellCheckTimer: Map<          string          , number> = new Map();        

          let checkerId = 0;        

          function checkElement(el: HTMLElement) {        

              let attr = el.getAttribute(SpellCheckAttribute);        

              if (attr) {        

                  clearTimeout(SpellCheckTimer.get(attr));        

                  let timer = setTimeout(() => { checkElementAsync(el) }, 500);        

                  SpellCheckTimer.set(attr, timer)        

              }        

          }        

          function checkText(words?: string | null): [string?] {        

              if (!words) {        

                  return [];        

              }        

              let errorWordList: [string?] = [];        

              try {        

                  let wordsList = words.match(/[a-zA-Z]+/ig);        

                  wordsList?.forEach((word) => {        

                      if (!checkWord(word)) {        

                          errorWordList.push(word);        

                      }        

                  })        

              }        

              catch {        



              }        

              return errorWordList;        

          }        

          function checkWord(text: string) {        

              //Simulate spell checking, and other check libraries are used here        

              return text.length > 6 ? false : true;        

          }        

          function checkElementAsync(el: HTMLElement) {        



              let text = (el as HTMLInputElement).value || el.innerText;        

              let result = checkText(text);        



              let attr = el.getAttribute(SpellCheckAttribute);        

              if (!attr) {        

                  return;        

              }        



              if (result && result.length) {        

                  el.style.background = "pink"        

                  let div = document.getElementById(attr);        

                  if (!div) {        

                      div = document.createElement("div");        

                      div.id = attr;        

                      div.style.position = "absolute"        

                      div.style.top = "0px"        

                      div.style.left = el.clientWidth + "px"        



                      if (el.parentElement) {        

                          el.parentElement.style.position = "relative"        

                          if (el.parentElement.lastChild === el) {        

                              el.parentElement.appendChild(div);        

                          }        

                          else {        

                              el.parentElement.insertBefore(div, el.nextSibling);        

                          }        

                      }        

                  }        

                  div.innerHTML = result.length.toString() + " - " + result.join(",");        

              } else {        

                  el.style.background = "";        



                  let div = document.getElementById(attr);        

                  if (div) {        

                      div.innerHTML = ""        

                  }        

              }        



              console.log(result)        

          }        



          app.directive('spell-check', {        

              created() {        

                  console.log("created", arguments)        

              },        

              mounted: function (el, binding, vnode, oldVnode) {        



                  console.log("mounted", arguments)        

                  //set checker id for parent        

                  let attr = "spellcheck-" + (checkerId++);        

                  el.setAttribute(SpellCheckAttribute, attr);        

                  console.log("attr", attr)        



                  if (el.tagName.toUpperCase() === "DIV") {        

                      el.addEventListener("blur", function () {        

                          checkElement(el)        

                      }, false);        

                  }        

                  if (el.tagName.toUpperCase() === "INPUT") {        

                      el.addEventListener("keyup", function () {        

                          checkElement(el)        

                      }, false);        

                  }        

                  // el.addEventListener("focus", function () {        

                  //     checkElement(el)        

                  // }, false);        

              },        

              updated: function (el) {        

                  console.log("componentUpdated", arguments)        

                  checkElement(el);        

              },        

              unmounted: function (el) {        

                  console.log("unmounted", arguments)        



                  let attr = el.getAttribute(SpellCheckAttribute);        

                  if (attr) {        

                      let div = document.getElementById(attr);        

                      if (div) {        

                          div.remove();        

                      }        

                  }        

              }        

          })        

}

  

main. Using plug-ins in TS

/// < reference path="./vue-app.d.ts" />

import { createApp } from 'vue'

import App from './App.vue'

import router from './router'

import SpellCheckPlugin from './plugins/SpellCheckPlugin'

let app = createApp(App)

app.use(SpellCheckPlugin)

app.use(router).mount('#app')

You can use instructions directly in the component

< template >

        <          div                     ref="ssHost" style="width: 100%; height: 600px">          div          >        

        <          div          ><          div                     ref="fbHost" spell-check v-spell-check="true" contenteditable="true" spellcheck="false" style="border: 1px solid #808080;width:600px;">          div          >          div          >        

        <          div          ><          input                     v-model="value1" v-spell-check spellcheck="false" style="width:200px;" />          div          >        

     template          >        

  

Combined with the use of SpreadJS, based on the function of checking users' spelling input, the effect is as follows:

The above is the introduction of some playing methods of Vue3 custom instruction development. If you know more using methods, you are welcome to share them by leaving a message.

Keywords: node.js html5 React Vue.js html

Added by MadRhino on Thu, 03 Feb 2022 03:50:23 +0200