# 1.directives 局部指令

vue
<template>
  <div>
    <input type="text" v-focus />
  </div>
</template>
<script>
export default {
  // 局部指令
  directives: {
    focus: {
      mounted(el, bindings, vnode, preVnode) {
        el.focus();
        console.log("el:", el);
        console.log("bindings:", bindings);
        console.log("vnode:", vnode);
        console.log("preVnode:", preVnode);
      },
    },
  },
};
</script>
<style scoped></style>

参考结果:

directives_default

  • el: 元素
  • bindings: 修饰符与参数
  • vnode: 虚拟节点
  • preVnode:前一个虚拟节点

# 2.directives 全局指令

app.directive('focus', {
  mounted(el,bindings,vnode,preVnode) {
    el.focus();
    console.log("el:", el);
    console.log("bindings:", bindings);
    console.log("vnode:", vnode);
    console.log("preVnode:", preVnode);
  }
})

参考结果:打印与上面结果是一样的,但这是全局的!

# 3.directives 生命周期

vue
<template>
  <div>
    <button v-if="counter < 3" v-why.a.b="'aimer'" @click="increment">
      当前计数: {{ counter }}
    </button>
  </div>
</template>
<script>
import { ref } from "vue";
export default {
  // 局部指令
  directives: {
    why: {
      created(el, bindings, vnode, preVnode) {
        console.log("created");
        console.log("el:", el);
        console.log("bindings:", bindings);
        console.log("vnode:", vnode);
        console.log("preVnode:", preVnode);
        console.log("------------------------------");
      },
      beforeMount() {
        console.log("beforeMounted:");
      },
      mounted() {
        console.log("mounted:");
      },
      beforeUpdate() {
        console.log("beforeUpdate:");
      },
      updated(el, bindings, vnode, preVnode) {
        console.log("update:");
        console.log("el:", el);
        console.log("bindings:", bindings);
        console.log("vnode:", vnode);
        console.log("preVnode:", preVnode);
        console.log("------------------------------");
      },
      beforeUnmount() {
        console.log("beforeUnmount:");
      },
      unmounted() {
        console.log("unmounted:");
      },
    },
  },
  setup() {
    const counter = ref(0);
    const increment = () => counter.value++;
    return {
      counter,
      increment,
    };
  },
};
</script>
<style scoped></style>

参考结果:

directives_life-cycle

  • created:在绑定元素的 attribute 或事件监听器被应用之前调用;
  • beforeMount:当指令第一次绑定到元素并且在挂载父组件之前调用;
  • mounted:在绑定元素的父组件被挂载后调用;
  • beforeUpdate:在更新包含组件的 VNode 之前调用;
  • updated:在包含组件的 VNode 及其子组件的 VNode 更新后调用;
  • beforeUnmount:在卸载绑定元素的父组件之前调用;
  • unmounted:当指令与元素解除绑定且父组件已卸载时,只调用一次;

# 4.directives format-time

npm install dayjs // 安装插件

# main.js

import { createApp } from 'vue'
import App from './App.vue'
import registerDirectives from './directives'
const app = createApp(App);
// 把实例 app 传入
registerDirectives(app);
app.mount('#app');

# format-time

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);
      // 10 位为秒 13 位为毫秒
      if (textContent.length === 10) {
        timestamp = timestamp * 1000 // 转换为毫秒
      }
      // 传入时间戳 (ms) format 传入格式
      el.textContent = dayjs(timestamp).format(bindings.formatString);
    }
  })
}

# App

vue
<template>
  <!-- 自定义指令 v-format-time:传入时间格式 -->
  <h2 v-format-time="'YYYY/MM/DD HH:mm:ss'">{{ timestamp }}</h2>
</template>
<script>
import { onMounted } from "vue";
export default {
  mounted() {
    console.log("Options API mounted");
  },
  setup() {
    const timestamp = 1628326173;
    onMounted(() => {
      console.log("Composition API  mounted");
    });
    return {
      timestamp,
    };
  },
};
</script>
<style scoped></style>

参考结果:

directives_format-time

​ directives 生命周期 & Options API 生命周期 & Composition API 生命周期 执行顺序

directives_execution_sequence