Custom instruction

Introduction to the

In addition to the default built-in directives (such as V-model and V-show), Vue also allows you to register custom directives.

For example, when the page loads, the input element gets focus.

By registering global directives

<body>
  <div id="app">
    <input type="text" v-focus />
  </div>

  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const { createApp, directive } = Vue;
    const Root = {};
    const app = createApp(Root);

    // Register the global directive
    app.directive("focus", {
      mounted(el) {
        // executes when the bound element is mounted into the DOM
        // el represents the element to which the directive is boundel.focus(); }}); app.mount("#app");
  </script>
</body>
Copy the code


This is done by registering local directives

<body>
  <div id="app">
    <! -- v-focus is a local directive, can only be used in my-Component components, otherwise error -->
    <! -- <input type="text" v-focus /> -->
    <my-component></my-component>
  </div>

  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const { createApp, directive } = Vue;
    const Root = {};
    const app = createApp(Root);

    app.component("my-component", {
      template: `<div><input type="text" v-focus /></div>`.directives: {
        focus: {
          mounted(el){ el.focus(); }},}}); app.mount("#app");
  </script>
</body>
Copy the code


Hook function

Hook function Execution time
created Called before the attribute or event listener of the bound element is applied.
beforeMount Called before the element of the bound directive is mounted into the DOM
mounted Called after the element of the bound directive is mounted into the DOM
beforeUpdate Called before the component in which the element of the bound directive is updated
updated Called after the component of the element to which the directive is bound is updated
beforeUnmount Called before the component in which the element of the bound directive is unloaded
unmounted Called after the component in which the element of the bound directive is unloaded
<body>
  <div id="app">
    <my-component v-if="isShow"></my-component>
    <button @click="rootClick">switch</button>
  </div>

  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const { createApp, directive, ref } = Vue;
    const Root = {
      setup() {
        const isShow = ref(true);
        const rootClick = function () { isShow.value = ! isShow.value }return{ isShow, rootClick }; }};const app = createApp(Root);

    app.directive("test", {
      created() {
        console.log("created...");
      },
      beforeMount() {
        console.log("beforeMount...");
      },
      mounted() {
        console.log("mounted...");
      },
      beforeUpdate() {
        console.log("beforeUpdate...");
      },
      updated() {
        console.log("updated...");
      },
      beforeUnmount() {
        console.log("beforeUnmount...");
      },
      unmounted() {
        console.log("unmounted"); }}); app.component("my-component", {
      name: "my-component".template: ` 
        

my-component

{{ count }}
`
.setup() { const count = ref("100"); const myClick = function () { count.value++; }; return{ count, myClick, }; }}); app.mount("#app");
</script>
</body> Copy the code


Dynamic instruction parameter

The parameters and binding values of instructions can be dynamic.

<body>
  <div id="app">
    <div
      style="width: 50px; height: 50px; background: pink"
      v-padding:[direction] ="distance"
    ></div>
    <div>
      <button @click="rootClick">{{ direction }}</button>
    </div>
    <div>
      <input type="range" min="0" max="50" v-model="distance" />{{ distance }}
    </div>
  </div>

  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const { createApp, directive, ref } = Vue;
    const Root = {
      setup() {
        const direction = ref("Start");
        const distance = ref("0");
        const arr = [
          "border-top"."border-right"."border-bottom"."border-left",];let index = 0;

        const rootClick = function () {
          index > 3 ? (index = 0) : "";
          direction.value = arr[index++];
        };

        return{ direction, distance, rootClick, }; }};const app = createApp(Root);

    app.directive("padding", {
      updated(el, binding) {
        el.style.border = "unset";
        el.style[binding.arg] = binding.value + "px" + " solid orange"; }}); app.mount("#app");
  </script>
</body>
Copy the code


Function shorthand

If you want to trigger the same behavior when Mounted and updated, regardless of the other hook functions. You can pass in a function at the second argument.

<body>
  <div id="app">
    <input type="text" v-focus />
    {{counter }}
    <button @click="myClick">update</button>
  </div>

  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const { createApp, directive, ref } = Vue;
    const Root = {
      setup() {
        const counter = ref('0')
        const myClick = function () {
          counter.value++
        }

        return {
          counter,
          myClick
        }
      },
    };
    const app = createApp(Root);

    app.directive("focus".(el, binding) = > {
      console.log("Executed...");
    });

    app.mount("#app");
  </script>
</body>
Copy the code

Object literals

If an instruction requires more than one value, you can pass in a JS object literal.

<body>
  <div id="app">
    <input type="text" v-user="{ name: 'cezlz', age: 18 }" />
  </div>

  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const { createApp, directive, ref } = Vue;
    const Root = {};
    const app = createApp(Root);

    app.directive("user".(el, binding) = > {
      console.log(binding.value);
    });

    app.mount("#app");
  </script>
</body>
Copy the code


Used in components

When used in a component, custom directives are always applied to the root node of the component.

<body>
  <div id="app">
    <my-component v-test></my-component>
  </div>

  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const { createApp, directive } = Vue;
    const Root = {};
    const app = createApp(Root);

    app.directive("test".(el, binding) = > {
      console.log(el.id)
    });

    app.component("my-component", {
      name: "my-component".template: ` 
        
my-component
`
}); app.mount("#app");
</script>
</body> Copy the code

The result is box1 printed, indicating that the custom directive is applied to the root node.


If the component has more than one root node, the custom directive is ignored and a warning is thrown.

<body>
  <div id="app">
    <my-component v-test></my-component>
  </div>

  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const { createApp, directive } = Vue;
    const Root = {};
    const app = createApp(Root);

    app.directive("test".(el, binding) = > {
      console.log(el.id)
    });

    app.component("my-component", {
      name: "my-component".template: ` 
        
my-component
my-component
`
}); app.mount("#app");
</script>
</body> Copy the code

Box1 is now not printed, indicating that the custom instruction has been ignored.