Read Vue's custom instructions in one article

你越是认真生活,你的生活就会越美好——Frank Lloyd Wright
"Fruit of Life" Classic Quotations

The content of the article comes from the custom command of Vue official website -vue official website

Introduction

VueIn addition to the default built-in directives ( v-modeland v-show) for core functionality, Vue also allows 注册自定义指令.

Note that Vue2.0in , the main forms of 代码复用and 抽象are 组件. However, in some cases, you still need it 对普通 DOM 元素进行底层操作, and this time it will be used 自定义指令.

An example of a focused input box is as follows:

<div id="simplest-directive-example" class="demo"><input></div>

insert image description here

When the page loads, 该元素将获得焦点(note: autofocusdoes not work on mobile Safari).
In fact, as long as you haven't clicked on anything since opening the page, the input should still be focused. Now let's 用指令来实现这个功能:

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
    
    
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) {
    
    
    // 聚焦元素
    el.focus()
  }
})

If you want to register 局部指令, the component also accepts directivesan option:

directives: {
    
    
  focus: {
    
    
    // 指令的定义
    inserted: function (el) {
    
    
      el.focus()
    }
  }
}

Then you can 在模板中use the new v-focusproperty on any element, like this:

<input v-focus>

hook function

An instruction definition object can provide the following 钩子函数(all optional):

  • bind: Called only once, when the directive is bound to the element for the first time. One-time initialization settings can be performed here.

  • inserted: 被绑定元素插入父节点时call (only guarantees that the parent node exists, but not necessarily has been inserted into the document).

  • update: The component's VNode 更新时call , but may occur before its child VNode is updated. The value of the directive may or may not have changed. But you can ignore unnecessary template updates by comparing the values ​​before and after the update (see below for detailed hook function parameters).

  • componentUpdated: Called after the VNode of the component where the command is located and its child VNodes are all updated.

  • unbind: Called only once, when the directive is unbound from the element.

Next, let's take a look at the parameters of the hook function (ie el、binding、vnode 和 oldVnode).

Hook function parameters

指令钩子函数Will be passed the following parameters:

  • el: The element bound to the instruction can be used to directly manipulate the DOM.
  • binding: An object containing the following properties:
    • name: Command name, excluding the v- prefix.
    • value: The binding value of the command, for example: v-my-directive="1 + 1"medium, the binding value is 2.
    • oldValue: The previous value to which the directive was bound, only available in update and componentUpdated hooks. Available whether or not the value has changed.
    • expression: Instruction expression in string form. For v-my-directive="1 + 1"example , the expression is "1 + 1".
    • arg: Parameters passed to the command, optional. For example, v-my-directive:fooin , the parameter is "foo".
    • modifiers: An object containing modifiers. For example: v-my-directive.foo.barin, the modifier object is { foo: true, bar: true }.
  • vnode: The virtual node generated by Vue compilation. Move to VNode API for more details.
  • oldVnode: Previous virtual node, only available in update and componentUpdated hooks.

Except el, 其它参数都应该是只读的, 切勿进行修改. If it needs to be between hooks 共享数据, it is recommended to 元素的 datasetdo it through.

Here is an example of a custom hook using these properties:

<div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
Vue.directive('demo', {
    
    
  bind: function (el, binding, vnode) {
    
    
    var s = JSON.stringify
    el.innerHTML =
      'name: '       + s(binding.name) + '<br>' +
      'value: '      + s(binding.value) + '<br>' +
      'expression: ' + s(binding.expression) + '<br>' +
      'argument: '   + s(binding.arg) + '<br>' +
      'modifiers: '  + s(binding.modifiers) + '<br>' +
      'vnode keys: ' + Object.keys(vnode).join(', ')
  }
})

new Vue({
    
    
  el: '#hook-arguments-example',
  data: {
    
    
    message: 'hello!'
  }
})

insert image description here

Dynamic command parameters

Parameters to directives can be dynamic. For example, v-mydirective:[argument]="value"in , argumentparameters can be updated based on component instance data! This allows custom instructions to be used flexibly in applications.

For example, if you want to create a custom directive for 通过固定布局将元素固定在页面上.

We can create a 更新竖直位置像素值custom directive with directive value like this:

<div id="baseexample">
  <p>Scroll down the page</p>
  <p v-pin="200">Stick me 200px from the top of the page</p>
</div>
Vue.directive('pin', {
    
    
  bind: function (el, binding, vnode) {
    
    
    el.style.position = 'fixed'
    el.style.top = binding.value + 'px'
  }
})

new Vue({
    
    
  el: '#baseexample'
})

This will be 把该元素固定在距离页面顶部 200 像素the location.

But what if the scenario is that we need to fix the element to the left instead of the top? At this time, 动态参数it is very convenient to update according to each component instance.

<div id="dynamicexample">
  <h3>Scroll down inside this section ↓</h3>
  <p v-pin:[direction]="200">I am pinned onto the page at 200px to the left.</p>
</div>
Vue.directive('pin', {
    
    
  bind: function (el, binding, vnode) {
    
    
    el.style.position = 'fixed'
    var s = (binding.arg == 'left' ? 'left' : 'top')
    el.style[s] = binding.value + 'px'
  }
})

new Vue({
    
    
  el: '#dynamicexample',
  data: function () {
    
    
    return {
    
    
      direction: 'left'
    }
  }
})

The result is as follows
insert image description here
so that this custom directive is now flexible enough to support a few different use cases.

function shorthand

In many cases, you may want bindto updatetrigger the same behavior on and , regardless of other hooks. For example, write like this:

Vue.directive('color-swatch', function (el, binding) {
    
    
  el.style.backgroundColor = binding.value
})

object literal

If the directive requires multiple values, one can be passed in JavaScript 对象字面量. Remember, directive functions accept all valid JavaScript expressions.

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

used in the project

Judging whether the relevant button is displayed according to the authority

src/plugins/directives.js
Used for permission management, here it is mainly to determine whether there is a corresponding editing permission to determine whether the relevant buttons are displayed

import Vue from 'vue'
import {
    
     getAlias } from '@/utils/tool'
import store from '../store'

const directives = {
    
    
  // 权限配置
  permission: {
    
    
    inserted(el, {
     
      arg }) {
    
    
    // getAlias()方法返回登录角色的权限别名数组 arg是使用自定义组件时传入的别名 如果传入的权限别名不在数组里 就会去掉对应的元素 不展示
      if (getAlias(store.state.permissionTree).includes(arg)) return
      let parent = el.parentElement
      parent.removeChild(el)
    }
  }
}

// 全局directives
Object.keys(directives).forEach((directiveName) => {
    
    
  Vue.directive(directiveName, directives[directiveName])
})

src/main.js 引入

import './plugins/directives'

The component uses the following ( update-accountis the alias of the permission to edit the account)
v-permissioncustom command function. If you have this permission, you will display the div element normally. If you don’t have this permission, you will hide it.

<div class="footer" v-permission:update-account>
<!--相关按钮-->
</div>

recommended reading

Vue source code learning complete directory


谢谢你阅读到了最后~
期待你关注、收藏、评论、点赞~
让我们一起 变得更强

Guess you like

Origin blog.csdn.net/weixin_42752574/article/details/119406703