Detailed explanation of user-defined instructions of vue3

1, Understanding custom instructions

In Vue's template syntax, we have learned various instructions: v-show, v-for, v-model, etc. in addition to using these instructions, Vue also allows us to customize our own instructions
  • Note: in Vue, code reuse and abstraction are mainly through components
  • Usually, in some cases, you need to perform the underlying operation on DOM elements, and custom instructions will be used at this time

There are two types of custom instructions

  • Custom local directives: the directives option in the component can only be used in the current component
  • In the global directive, any method can be used

For example, let's take a very simple case: when an element is mounted, you can get the focus by yourself

  • Implementation method 1: if we use the default implementation method
<template>
  <div>
    <input type="text" ref="input" />
  </div>
</template>

<script>
import { ref, onMounted } from "vue";

export default {
  setup () {
    const input = ref(null);

    onMounted(() => {
      input.value.focus();
    })

    return {
      input
    }
  }
}
</script>

<style scoped>
</style>
  • Implementation mode 2: customize a local instruction of v-focus
<template>
  <div>
    <input type="text" v-focus>
  </div>
</template>

<script>
  export default {
    // Local instruction
    directives: {
      focus: {
        mounted(el, bindings, vnode, preVnode) {
          console.log("focus mounted");
          el.focus();
        }
      }
    }
  }
</script>

<style scoped>

</style>
  • Implementation method 3: customize a global instruction of v-focus
 app.directive("focus", {
   mounted(el, bindings, vnode, preVnode) {
     console.log("focus mounted");
     el.focus();
   }
 })

2, Instruction life cycle

An object defined by an instruction. Vue provides the following hook functions

  • created: top note before the attribute of the binding element or the event listener is applied.
  • beforeMount: when the instruction is bound to the element for the first time and is called before the parent component is mounted.
  • Base note: mounted: after the parent component of the binding element is mounted, it is called.
  • Top note: beforeUpdate: before updating the VNode containing the component.
  • updated: call after updating the VNode of the component and its sub components after updating the VNode.
  • Top note: beforeUnmount: before calling the parent component of the binding element.
  • unmounted: only called once when the instruction is unbound from the element and the parent component has been unloaded;
<template>
  <div>
    <button v-if="counter < 2" v-why @click="increment">Current count: {{counter}}</button>
  </div>
</template>

<script>
  import { ref } from "vue";

  export default {
    // Local instruction
    directives: {
      why: {
        created(el, bindings, vnode, preVnode) {
          console.log("why created", el, bindings, vnode, preVnode);
          console.log(bindings.value);
          console.log(bindings.modifiers);
        },
        beforeMount() {
          console.log("why beforeMount");
        },
        mounted() {
          console.log("why mounted");
        },
        beforeUpdate() {
          console.log("why beforeUpdate");
        },
        updated() {
          console.log("why updated");
        },
        beforeUnmount() {
          console.log("why beforeUnmount");
        },
        unmounted() {
          console.log("why unmounted");
        }
      }
    },
    setup() {
      const counter = ref(0);
      const increment = () => counter.value++;

      return {
        counter,
        increment
      }
    }
  }
</script>

<style scoped>

</style>

3, Parameters and modifiers of the directive

  • If our instruction needs to accept some parameters or modifiers, how should we operate?
  • info is the name of the parameter
  • AAA BBB is the name of the modifier
  • Followed by the specific value passed in
  • In our life cycle, we can get the corresponding content through bindings

4, Custom instruction exercise

  • User defined instruction case: display requirements of timestamp
  • In development, in most cases, time stamps are obtained from the server
  • We need to convert the timestamp into a specific formatted time to display
  • In Vue2, we can do this through filters
  • In Vue3, we can calculate attributes or customize a method
  • In fact, we can also complete it through a user-defined instruction
  • Let's implement an instruction v-format-time that can automatically format time
  • Here we encapsulate a function. On the home page, we only need to call this function and pass it into the app

directory structure

format-time.js

import dayjs from 'dayjs';

export default function(app) {
  app.directive("format-time", {
    created(el, bindings) {
      bindings.formatString = "YYYY-MM-DD HH:mm:ss";
      if (bindings.value) {
        bindings.formatString = bindings.value;
      }
    },
    mounted(el, bindings) {
      const textContent = el.textContent;
      let timestamp = parseInt(textContent);
      if (textContent.length === 10) {
        timestamp = timestamp * 1000
      }
      el.textContent = dayjs(timestamp).format(bindings.formatString);
    }
  })
}

index.js

import registerFormatTime from './format-time';

export default function registerDirectives(app) {
  registerFormatTime(app);
}

App.vue

<template>
  <h2 v-format-time="'YYYY/MM/DD'">{{timestamp}}</h2>

  <h2 v-format-time>{{timestamp}}</h2>
  <h2 v-format-time>{{timestamp}}</h2>
  <h2 v-format-time>{{timestamp}}</h2>
  <h2 v-format-time>{{timestamp}}</h2>
  <h2 v-format-time>{{timestamp}}</h2>

</template>

<script>
  export default {
    setup() {
      const timestamp = 1624452193;

      return {
        timestamp
      }
    },
    mounted() {
      console.log("app mounted");
    }
  }
</script>

<style scoped>

</style>

main.js

import { createApp } from 'vue'
import App from './03_Custom instruction/App.vue'
import registerDirectives from './directives'

const app = createApp(App);

registerDirectives(app);

app.mount('#app');

Tags: Front-end Javascript Vue.js

Posted by DigitHeads on Mon, 18 Apr 2022 21:06:57 +0930