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');