This is the first day of my participation in the August More Text challenge


series

  • Vue 3 basis
  • Vue 3 dynamic effect
  • Vue 3 components
  • Modular API
  • Vue Router Next
  • Vuex 4

This article introduces the basic usage of Vue 3, focusing on the differences between 🎉 and Vue 2.

Install the introduction

You can use CDN to introduce the latest version of the Vue 3 framework

<script src="https://unpkg.com/vue@next"></script>
Copy the code

You can then access the exposed Vue object or its method createApp() to create a Vue instance.

You can also install using NPM

# The latest stable version
$ npm install vue@next
Copy the code

And introduce Vue (or createApp destructively) in the entry file main.js or main.ts.

import { createApp } from 'vue'
Copy the code

Initialize the

Use Vue’s 🎉 method.createApp() to create a Vue instance application that accepts an object whose properties are the configuration options for the root component. It then mounts the Vue instance to the specified DOM using the instance method.mount(el), rendering the data into the page in a responsive manner.

<div>
    <div id="app"></div>
</div>
Copy the code
<script>
const app = Vue.createApp({
  data() {
    return {
      conent: 'Hello World! '}}template: '<div>{{ conent }}</div>'
})

app.mount('#app')
</script>
Copy the code

🎉 The mounted application does not replace elements, that is, when we mount an application, its render replaces the innerHTML (as a child) of the element specified in mount(el)

Most methods exposed by 💡 application instances return that same instance, so 🎉 allows multiple global configurations of the same instance in a chained fashion

Vue.createApp({})
  .component('SearchInput', SearchInputComponent) // Register the global component
  .directive('focus', FocusDirective) // Register the global custom directive
  .use(LocalePlugin) // Use plugins
Copy the code

💡 When the Vue instance is mounted to the page, the method.mount() returns not the application itself, but the root component instance, which is 🎉, a Proxy object that is the VM View data connection layer in the MVVM design pattern.

const app = Vue.createApp({
    data() {
        return {
            content: 'Hello World! '}}template: '<div>{{ content }}</div>'
});

const vm = app.mount('#app');
Copy the code

The component’s property is exposed through the component instance, which can be accessed in the component’s template; They can also be accessed in component options, or even in development mode from the developer tools terminal of the browser, with a $prefix to avoid conflicts with user-defined property names.

console.log(vm.$data.content)
// The data option can also be accessed directly
console.log(vm.content)
Copy the code

Attributes bind

Using the directive V-bind in the template to bind the attributes of the tag to dynamic data, you achieve data-driven graphics (styles).

The instruction V-bind :attrName=”value” can be abbreviated to :attrName=”value”, binding values can be strings, objects, arrays, etc.

💡 For the class and style attributes, Vue implements special optimization enhancements for these two attributes. In addition to strings, binding values can also be objects or arrays. It also merges dynamically bound data with static data for that attribute (the other attributes are “back-cover front”).

⚠️ If the bound value is null or undefined, the attribute will not be included on the rendered element.

💡 For Boolean attributes (which are true if they exist), the element is rendered only for Truthy and not for Falsy, but for empty strings “”, it is also included, This is in keeping with the form of

Child component Attribute inheritance

When the component returns a single root node, non-prop attributes are automatically added to the attributes of the root node.

💡 A non-prop attribute refers to a component that does not have an attribute defined for props or emits. Common examples include class, style, and ID attributes.

💡 If you don’t want the component’s root element to inherit attributes, you can set inheritAttrs: false in the component’s options. A common case for disabling attribute inheritance is when you need to apply the attribute to elements other than the root node.

Then manually bind v-bind=”$attrs” to the desired node by accessing the component’s $attrs property, which includes all properties not included in the component props and emits property, You can apply the corresponding Attribute to the node.

🎉 in Vue 3 $attrs contains all the attributes passed to the component, including class and style.

app.component('date-picker', {
  inheritAttrs: false.template: ` 
      
`
}) Copy the code

Since Vue 3 supports components with multiple root nodes, if the component’s template has multiple root nodes 🎉, you must explicitly specify with $attrs which node non-prop attributes are bound to, otherwise a warning will pop up.

// This will issue a warning
app.component('custom-layout', {
  template: ` 
      
...
...
...
`
}) $attrs is passed to the
element without warning
app.component('custom-layout', { template: `
...
...
...
`
}) Copy the code

💡 can also bind a specified Attribute, for example, binding only the class Attribute to the first root node; All non-props passed in can be accessed in the business logic of the component configuration parameter via this.$attrs

<div id="app">
  <my-component class="baz"></my-component>
</div>
Copy the code
app.component('custom-layout', {template:` 
      
Hellp
World
`
}) Copy the code

Two-way binding

In the label of the template, the instruction V-model is used to realize the bidirectional binding between the value of the form and the dynamic data, and the input data of the ,

💡 V-Model is essentially a syntax sugar that internally listens for different properties for different form elements in response to user input, throws different events, and then modifies the binding’s reactive data in the event handler function, implementing bi-directional binding, and customizing the corresponding event handler if needed.

Internally, the V-Model uses different properties for different input elements and throws different events:

  • <input type="text"><textarea>Elements usingvalueThe property andinputThe event
  • <input type="checkbox "><input type="radio">usecheckedThe property andchangeThe event
  • <select>Field willvalueAs prop and willchangeAs the event

⚠️ does not work in the textarea

Vue provides some modifiers that make it easy to set form input values:

  • Form values are strings by default, and you can use form modifiers if you want the bound dynamic data variable to hold a numeric typev-model.number
  • Form modifierv-model.trimAutomatically filter the first and last blank characters entered by the user
  • Form modifierv-model.lazychangeData synchronization occurs after the event (after losing focus) (default is ininputEvent triggered)

💡 For radio buttons, check boxes, and selection boxes, it is sometimes desirable that the final values of these forms be set separately, so that the corresponding form values (even complex data structures such as objects) can be derived based on the value of the bidirectional binding.

  • Check box: True -value and false-value attributes can be used

    <input type="checkbox" v-model="toggle" true-value="yes" false-value="no" />
    Copy the code
    // when checked:
    vm.toggle === 'yes'
    // when unchecked:
    vm.toggle === 'no'
    Copy the code
  • Option box: You can bind the value property

    <input type="radio" v-model="pick" v-bind:value="a" />
    Copy the code
    // when selected
    vm.pick === vm.a
    Copy the code
  • Box options: Bind the value attribute of the

    <select v-model="selected">
      <! Inline object literals -->
      <option :value="{ number: 123 }">123</option>
    </select>
    Copy the code
    // When selected
    typeof vm.selected // => 'object'
    vm.selected.number / / = > 123
    Copy the code

Use v-Models on components

When using custom input components, Vue optimizes them and also supports bidirectional binding using v-Models.

<custom-input v-model="searchText"></custom-input>

<! -- equivalent to the following code
<custom-input
  :model-value="searchText"
  @update:model-value="searchText = $event"
></custom-input>
Copy the code

Externally (on the label of the component when referencing the component) the variable to be synchronized is bidirectionally bound by the instruction V-Model, whose data is passed inside the component by default as a prop 🎉 named modelValue (so remember inside the component, You need to declare modelValue as prop in the props option, as the value property of the form element inside the child component.

It only needs to be handled within these components:

  • Use directives within componentsv-bindOf a form elementvalueProperty bound to the prop variable declared abovemodelValueOn, that is,v-bind:value="modelValue"(This allows you to “synchronize” the external data by taking the value passed in as the form’s value.)
  • Use directives within componentsv-onListening for form elementsinputEnter the event and passthrowupdate:modelValueThe event $emit('update:modelValue', $event.target.value)The corresponding data is passed outwards, and the external world receives the thrown event and responds to the instructionv-modelBound variables change based on thrown data(That is, the operation of data modification is still done in the parent layer)
// conpoment
app.component('custom-input', {
  props: ['modelValue'].emits: ['update:modelValue'].template: `  `
})
Copy the code
<custom-input v-model="searchText"></custom-input>
Copy the code

⚠️ Vue 2 provides the.sync modifier, with v-bind: propname. sync=”variable” and $emit(‘update:propName’, newValue) for bi-directional binding; But 🎉 was removed from Vue 3 with the.sync modifier, which is now implemented using a similar syntax (the component also throws events prefixed with update:).

The default prop variable passed is modelValue and the default to listen for thrown events is Update :modelValue. This method is more general and does not confuse the semantics of either type=”text” or type=checkbox. If you need to change the default value of modelValue, you can configure it in Vue 2 with the option model, but 🎉 has removed the option model in Vue 3. Instead, you can add parameters for V-model in the parent. The argument is the name of the prop variable and the name of the event to listen for (prefixed with update:).

<! -- Using components -->
<my-component v-model:title="bookTitle"></my-component>

<! -- is short for the following -->
<my-component :title="bookTitle" @update:title="bookTitle = $event" />
Copy the code
/ / component
app.component('my-component', {
  props: {
    title: String
  },
  emits: ['update:title'].template: `  `
})
Copy the code

In Vue 3, using a specific prop (by calling the component using the parameters of the directive V-Model) and throwing the corresponding events, 🎉 can create multiple V-Models on a single component, thus enabling bidirectional binding of multiple prop

<! -- use component to implement two-way binding between first-name and last-name -->
<user-name
  v-model:first-name="firstName"
  v-model:last-name="lastName"
></user-name>
Copy the code
app.component('user-name', {
  props: {
    firstName: String.lastName: String
  },
  emits: ['update:firstName'.'update:lastName'].template: `   `
})
Copy the code

Using the directive V-model on input components not only supports the built-in Vue modifiers.trim,.number,.lazy, 🎉 Vue 3, but also supports adding custom modifiers. Modifiers added to the component’s V-model are provided to the component through the modelModifiers Prop.

The 💡 modifier should come after the argument of the directive, and the modifier supports multiple chaining

<! Capitalizing a string with a custom modifier -->
<my-component v-model.capitalize="myText"></my-component>
Copy the code
/ / component
app.component('my-component', {
  props: {
    modelValue: String.// modelModifiers Prop here we provide the initial value
    modelModifiers: {
      default: () = >({})}},emits: ['update:modelValue'].methods: {
    // Form input event handler
    emitValue(e) {
      let value = e.target.value
      Capitalize the form input value if the V-Model has a capitalize modifier
      if (this.modelModifiers.capitalize) {
        value = value.charAt(0).toUpperCase() + value.slice(1)}// Throws an event
      this.$emit('update:modelValue', value)
    }
  },
  template: ` `.created() {
    // When a component's Created lifecycle hook fires, the modelModifiers Prop is set depending on how the component is called
    Because the V-Model modifier in this example is capitalize, the modelModifiers will include the capitalize attribute
    console.log(this.modelModifiers) // { capitalize: true }}})Copy the code

🎉 If the V-Model sets parameters, custom Modifiers added to the component V-Model will be provided to the component via prop in the form of arG + Modifiers.

<my-component v-model:description.capitalize="myText"></my-component>
Copy the code
app.component('my-component', {
  props: ['description'.'descriptionModifiers'].emits: ['update:description'].template: `  `.created() {
    console.log(this.descriptionModifiers) // { capitalize: true }}})Copy the code

Conditions apply colours to a drawing

Both the v-if and V-show directives allow conditional rendering, where elements are rendered or displayed only when the expression of the directive returns a truthy value.

In general, V-if has a higher switching overhead, while V-show has a higher initial rendering overhead. Therefore, v-show is good if you need to switch very frequently; It is better to use V-if if conditions rarely change at run time.

v-if

Use the v-if directive in the template tag to control rendering of the DOM, rendering elements only if the conditional directive is true, otherwise the DOM is “pulled out”.

💡 If you want to control conditional rendering of multiple elements at the same time, you can use the

You can also use V-if, V-else, and V-else to set conditional rendering of parallel elements of the same level. The elements of these three instructions need to be consecutive and identical.

💡 is no longer necessary for the v-if/ V-ELSE/V-else -if 🎉 branch key, as Vue now automatically generates a unique key. If you supply keys manually, each branch must use a unique key.

v-show

Using the directive V-show in the template tag also controls DOM rendering, showing elements only if the conditional directive is true, otherwise the DOM is hidden.

⚠️ v-show does not support

The list of rendering

Using the directive V-for in a template tag, you can render an array or object in responsive data as a series of DOM elements, called list rendering, commonly in the form V-for Item in ARR or V-for Item of ARR

  • You can iterate over arR arrays, obj objects, and number (starting at 1) numbers
  • But when iterating through an objList (an array-like object), there is no guarantee of the order in which items are iterated each time

One important thing is that you need to set the key attribute for the generated element, usually binding a unique identifier associated with the element (rather than using index directly) to make DOM updates more efficient.

The 💡 key attribute can also be used to force elements/components to be replaced rather than reused. It can be useful when you encounter situations like:

  • Triggers the component’s lifecycle hook completely
  • Trigger a transition

The directive V-for can be applied to the element

⚠️ 🎉 V-if will have a higher priority than V-for, which is the opposite of how it works in Vue 2. This also causes v-if to have no access to variables in V-for on the same element

<! -- This will throw an error because property "todo" is not defined on instance. -->

<li v-for="todo in todos" v-if=! "" todo.isComplete">
  {{ todo.name }}
</li>
Copy the code

The official documentation recommends using the

<template v-for="todo in todos" :key="todo.name">
  <li v-if=! "" todo.isComplete">
    {{ todo.name }}
  </li>
</template>
Copy the code

💡 Because objects and arrays are reference data types, modifying them often causes problems that do not trigger reactive changes properly, such as list rerendering. Vue is specifically optimized for the common array methods (push(), pop(), shift(), unshift(), splice(), sort(), reverse())). If you modify an array using these methods, Vue can listen. Dependencies change in response (whereas modifying the value of an array directly by subscript often does not trigger a view to update in response).

Teleport

Sometimes a part of the code in a component template logically belongs to that component, and from a UI perspective it is best to move that part of the template outside of the Vue app. For example, components in full-screen mode, such as modal boxes, should be direct children of elements rather than deeply nested in divs.

Teleport, a new addition to Vue 3, provides a clean way to freely control which page DOM nodes the templates in the container render under.

🎉 The built-in component

serves as a container, and its property to specifies which DOM node the content needs to be inserted into. The property value can be a tag name, such as body, or a CSS selector.

app.component('modal-button', {
  template: ` <button @click="modalOpen = true"> Open full screen modal! (With teleport!) </button> <! --> <teleport to="body"> <div V-if ="modalOpen" class="modal"> <div> I'm a teleported modal! (My parent is "body") <button @click="modalOpen = false"> Close </button> </div> </div> </teleport> `.data() {
    return {
      modalOpen: false}}})Copy the code

💡 When the < Teleport > container contains a Vue component, the logical parent-child component relationship does not change, even though the final rendering is under the specified DOM node, i.e. the injection from the parent component still works as expected, and in Vue Devtools, the child component will be nested under the parent component, It’s not where the actual content is moving.

💡 Multiple

components can be mounted to the same target element in appending mode, that is, later mounted elements are after earlier mounts. A common use case scenario is a reusable

component for pop-up messages, mounted under the element, Multiple instances may be active at the same time, and the effect from the UI perspective is that the new modal box overwrites the old one.

Responsive variable

When configuring a(root) component, you declare reactive variables in the 🎉 option data() function, and then pack them as return values in an object that Vue wraps through the reactive system and stores in the component instance VM as $data after the component instance is created.

This allows you to use them directly in the template, or use this.$data.varName (where this is the component instance VM, and the reactive object can also be accessed outside of Vue via vm. For convenience, any top-level property of the object can be exposed directly through the component instance, that is, by this.varname instead.

const app = Vue.createApp({
  data() {
    return { count: 4}}})console.log(vm.$data.count) / / 4
console.log(vm.count)       / / 4
Copy the code

⚠️ These properties are only added when the instance is first created, so you need to make sure they are all in the object returned by the data function. If necessary, use null, undefined, or other placeholder values for properties that have not yet provided the required value.

Evaluate properties and listeners

Create computed properties under the computed option and create listeners under the Watch option. Both perform operations based on changes in responsive data, but they have different uses.

computed

Attributes are often evaluated to extract complex and reusable data-processing logic from functional expressions in templates. It is used directly on the template as reactive data, just like the property of data.

The biggest advantage of computed properties is that they are cached for reactive dependencies, meaning that computed properties are reevaluated only when the associated reactive dependencies change. If you want the computed property to update in real time, it needs to have reactive dependencies (based on reactive data or other sources) and return a value.

💡 If you don’t want caching, use method instead to achieve the same functionality, in contrast, the method function will always be executed again whenever the component is triggered to re-render.

watch

You can think of Watch as a more general way to listen for response data. Watch also relies on responsive data, be it a Data property or computed Property (or a nested property of those properties), and then triggers a callback function when the responsive data changes, where you can perform asynchronous operations. Intermediate states can be set without returning a value.

Listeners can be set up in more detail in the form of functions (whose names are reactive variables to listen for) as well as objects

watch: {
  // listen for the responsive variable A
  a(val, oldVal) {
    console.log(`new: ${val}, old: ${oldVal}`)},// Callback function name to represent (string)
  b: 'someMethod'.// Object form
  // This callback is called whenever the property of any object being listened on changes, no matter how deeply nested it is
  c: {
    handler(val, oldVal) {
      console.log('c changed')},deep: true
  },
  // listen for nested properties
  'c.d': function (val, oldVal) {
  // do something
  },
  // This callback will be invoked immediately after the listening starts
  e: {
    handler(val, oldVal) {
      console.log('e changed')},immediate: true
  },
  // An array of callback functions that will be called one by one
  f: [
    'handle1'.function handle2(val, oldVal) {
      console.log('handle2 triggered')}, {handler: function handle3(val, oldVal) {
        console.log('handle3 triggered')}}]Copy the code

💡 In Vue 2, watch can generally listen on only one responsive data (if you want to listen on multiple variables, you can use the arrow function to combine them and return them to watch for a computed listener), and 🎉 in Vue 3, watch can listen on multiple data sources and responsive objects.

 // Listen on multiple sources
watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) = > {
  / *... * /
})
Copy the code

methods

Add methods to a component instance with the Methods option, which is an object where properties are methods that the component can call.

Methods can be called directly from the component template or through this.methodName([Params]) in other options.

⚠️ Vue automatically binds methods to this so that it always points to component instances, so you should avoid using arrow functions when defining these methods (because this prevents Vue from binding proper this Pointers).

The official documentation also mentions an example of anti-shaking that is worth noting. Due to component instantiation, the component of the methods in the choice of the function of this binding (pointing to a component instance), but or sharing function, so in the same page reuse component, to offer actual call the same function, can lead to not be the same as expected, the effect of concrete analysis can refer to this article.

Therefore, the right thing to do is to create a lifecycle hook by adding an anti-shock function to the component instance, so that each component has its own independent anti-shock function

app.component('save-button', {
  created() {
    // Encapsulate the event handler with Lodash's anti-shock function
    // This refers to the component instance
    // So the debouncedClick function is independent of each component instance
    this.debouncedClick = _.debounce(this.click, 500)},unmounted() {
    // When removing a component, cancel the timer
    this.debouncedClick.cancel()
  },
  methods: {
    click() {
      / /... The specific handler in response to a click...}},template: `  `
})
Copy the code

The event processing

Listen for events using the directive V-ON :event-name in the template’s tag, using the shorthand @event-name, and trigger the callback function.

💡 The event listeners set in the template need to be in kebab-case form

Its callback function passes the event event as an argument by default.

<div id="event-with-method">
  <! -- 'greet' is the method name defined below -->
  <button @click="greet">Greet</button>
</div>
Copy the code
// ...
methods: {
  greet(event) {
    // 'event' is a native DOM event
    console.log(event)
  }
}
Copy the code

If you want to pass both parameters and events, you can use the special $event variable to pass the event to the callback function (remember to set the parameters in the event handler function).

<button @click="warn('Form cannot be submitted yet.', $event)">
  Submit
</button>
Copy the code
// ...
methods: {
  warn(message, event) {
    // You can now access native events
    if (event) {
      event.preventDefault()
    }
    alert(message)
  }
}
Copy the code

💡 supports setting multiple handlers for the same event, separated by commas, in which case () is added to the callback function even if no arguments are passed.

<! -- The two one() and two() will execute the button click event -->
<button @click="handlerOne(), handlerTwo($event)">
  Submit
</button>
Copy the code

💡 supports v-on objects that bind an event/listener key-value pair without arguments. Note that no modifiers are supported when using object syntax.

<! -- Object Syntax (2.4.0+) -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>
Copy the code

Vue provides a variety of event modifiers to make it easier to set the behavior of events so that event handlers can have pure data logic instead of dealing with DOM event details. Event modifiers can be chained to multiple calls. The use of numbers (i.e. key codes) as V-ON modifiers is no longer supported in Vue 3

  • .stopStop the story from spreading
  • .preventPrevents the default behavior of an event, such as redirecting to a specified URL after a form submission
  • .selfEvent when the element itself firesBefore executing the event handler function
  • .onceInvalid after only responding to an event once
  • .captureUse event capture mode
  • .passiveforscrollEvents are optimized for improved performance. But don’t put the.passive.preventUse it together because.preventWill be ignored, and the browser may show you a warning.

For UI UI interaction events, such as mouse events and keystroke events, which are the most common, Vue provides mouse and keystroke modifiers that can directly convert any valid keyname exposed by keyboardevent. key to kebab-case as a modifier.

<! $event.key = 'PageDown' -->
<input @keyup.page-down="onPageDown" />
Copy the code

Throws a value using a custom event

When listening for thrown events between parent and child components, the child component throws the event in the template using the $emit() method. The first argument is the event name and the second argument (optional) is the data to pass (if you want to throw the child component’s event, you can use the special variable $event as an argument).

<button @click="$emit (0.1) 'enlargeText',">  Enlarge text</button>
Copy the code
<! Use $event to access click events of child components, and then throw as an argument to custom events; enlargeText;
<button @click="$emit('enlargeText', $event)">
  Enlarge text
</button>
Copy the code

This event is then listened for in the parent component, whose callback takes this data as its first argument

<blog-post . @enlarge-text="onEnlargeText"></blog-post>
Copy the code
methods: {
  onEnlargeText(enlargeAmount) {
    this.postFontSize += enlargeAmount
  }
}
Copy the code

💡 If the parent component does not use a callback function and uses inline processor writing directly, the value can be accessed using $event

<blog-post . @enlarge-text="postFontSize += $event"></blog-post>
Copy the code

Emits options

🎉 Vue 3 currently provides a emits option, similar to the options props, to define the events that a child component can trigger to its parent.

💡 strongly recommends using emits to log all events that can be triggered by each component.

<template>
  <div>
    <p>{{ text }}</p>
    <button v-on:click="$emit('accepted')">OK</button>
  </div>
</template>
<script>
  export default {
    props: ['text'].emits: ['accepted']}</script>
Copy the code

This option can accept a string as an array of elements or an object. You can set validators for events in objects, similar to the validators in the props definition.

🎉 In object syntax, the value of each property can be either NULL or the validation function that will receive the data passed when $emit is called. The validation function should return a Boolean value indicating whether the event parameter is valid.

const app = createApp({})

// Array syntax
app.component('todo-item', {
  emits: ['check'].created() {
    this.$emit('check')}})// Object syntax
app.component('reply-form', {
  emits: {
    // There is no validation function
    click: null.// with validation functions
    submit: payload= > {
      if (payload.email && payload.password) {
        return true
      } else {
        console.warn(`Invalid submit event payload! `)
        return false}}}})Copy the code

Custom instruction

Vue provides a variety of built-in directives, such as V-if, V-bind, V-ON, v-Model, for easy use in templates, and also allows the registration of custom directives.

Global registration

App. directive Registers a globally available custom directive through the root component instance method. The first parameter directiveName is the suffix of the directive. The second argument is to define the behavior of the directive. Vue provides hook functions for custom directives that can be called at different stages of the bound element:

  • 🎉 createdCalled before the attribute or event listener of the bound element is applied.An event listener needs to be attached to the instruction, whereas it needs to be attached to the normalv-onThis is useful when called in front of event listeners
  • 🎉 beforeMountCalled when the directive is first bound to an element and before the parent component is mounted
  • 🎉 mountedCalled after the parent component of the bound element has been mounted
  • 🎉 beforeUpdateCalled before updating the VNode containing the component
  • updatedIn a VNode that contains componentsVnodes and their childrenCall after update
  • 🎉 beforeUnmountCalled before unloading the parent component of the bound element
  • 🎉 unmountedIt is called only once when the directive is unbound from the element and the parent component is unmounted
const app = Vue.createApp({})
app.directive('directiveName', {
 // Directives are hooks with a lifecycle:
  Called before the attribute or event listener of the bound element is applied
  created() {},
  // called before the parent of the bound element is mounted
  beforeMount() {},
  // called when the parent of the bound element is mounted
  mounted() {},
  // called before the VNode containing the component is updated
  beforeUpdate() {},
  // called after a VNode update of the VNode containing the component and its children
  updated() {},
  // called before the parent component of the bound element is unloaded
  beforeUnmount() {},
  // Called when uninstalling the parent component of the bound element
  unmounted(){}})Copy the code

App. directive(‘directiveName’, (el, binding) => {… })

The directive’s hook function passes in the following arguments to manipulate the bound DOM element and pass data:

  • El is the element bound by the directive and can be used to manipulate the DOM directly

  • Binding is an object containing the following properties:

    • Instance A component instance that uses a directive

    • Value The value passed to the instruction. For example, in v-my-directive=”1 + 1″, the value is 2

    • OldValue Previous value, available only in beforeUpdate and updated. Whether or not the value has changed is available

    • The arG argument is passed to the instruction (if any). For example, in V-my-directive :foo, arg is foo

    • Modifiers are objects that contain modifiers (if any) (because a directive can have multiple modifiers, used in chained fashion with.a.b.c). For example, in v-my-directive.foo.bar, the modifier object is {foo: true, bar: true}.

    • Dir An object passed as a parameter when a directive is registered

      For example, in the following instructions

      app.directive('focus', {
        mounted(el) {
          el.focus()
        }
      })
      Copy the code

      Dir will be the following object

      {
        mounted(el) {
          el.focus()
        }
      }
      Copy the code
  • Vnode Virtual node generated by Vue compilation

  • PrevNode is a virtual node on prevNode, available only in beforeUpdate and updated hooks

This custom directive can then be used in any element of the Vue instance

💡 If the directive requires multiple values, you can pass in a JavaScript object literal.

<div v-demo="{ color: 'white', text: 'hello!' }"></div>
Copy the code
app.directive('demo'.(el, binding) = > {
  console.log(binding.value.color) // "white"
  console.log(binding.value.text) // "hello!"
})
Copy the code

⚠️ If you use both the arg parameter and the modifier when using directives, use the modifier in sequence (because there is only one ARG; And modifier can series more, should be in the last) v – directiveName: argument. The modifier

Local registration

Registers local directives in the component’s option Directives, which also provide 5 hook functions. You can then use custom directives on any element in the component’s template

// ...
directives: {
  directiveName: {
    // Set the hook function
    inserted: function (el) {}}}Copy the code

Apply to components

Like non-prop attributes, when used in components, custom directives are always applied to the root node of the component. But unlike attributes, directives cannot be passed to another element via v-bind=”$attrs”, 🎉 so when a custom directive is applied to a multi-root component, it is ignored and a warning is thrown.