Vue3中关于自定义指令的一些经历

文章目录

  • 前言
  • 从一个需求开始
    • 第一阶段
    • 第二阶段
    • 第三阶段
      • 自定义指令的注册
      • 解决自适应高度的问题

前言

自定义指令真的蛮好用,尤其是一些繁琐的很多组件都通用的监控,直接扔到指令里面就行。但是从vue2到vue3的演进过程里,指令的使用方式发生了比较大的变化,而且有一些坑,在这里记录一下。

  • Tips:本文默认你已经熟练使用vue2的自定义指令

从一个需求开始

需求:前端项目使用element-ui,其中el-table的表高在换不同显示屏的时候很难适配,需要一个统一的处理手段进行自适应,应该怎么做呢?

第一阶段

手动设定两三种表高,监听判断屏幕大小,然后匹配一下。这个实在太low,直接放弃

第二阶段

我最初的想法是写一个setInterval,每隔1秒钟扫一次document.clientHeight,来判断表高是否需要调整,代码如下:

setInterval(() => {
	const h = document.documentElement.clientHeight
	if(h !== oldHeight.value) {
		tableHeight.value = h * 0.6
		oldValue.value = h
	}
}, 1000)

但是这个有问题,每个需要调整表高的组件都要写一个监听,太繁琐且难以维护。放弃该方案

第三阶段

我们的directive闪亮登场。

自定义指令的注册

const app = Vue.createApp({})
// 注册一个全局自定义指令 `v-focus`
app.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  mounted(el) {
    // Focus the element
    el.focus()
  }
})

就写在前端项目的根文件main.js里面就好,就可以注册一个自定义指令。使用也很简单,直接把v-focus写在某个dom上就行:

<div v-focus>div>

解决自适应高度的问题

经过不断的研究,下面这种写法是比较靠谱的:

app.directive('resizer', {
  mounted: (el, binding) => {
    const tableHeight = () => {
      if (window.innerHeight >= 976) {
        el.style.height = '670px'
      } else {
        el.style.height = `${window.innerHeight - binding.value < 200 ? 200 : (window.innerHeight - binding.value)}px`
      }
    }
    tableHeight()
    el.tableHeight = tableHeight
    window.addEventListener('resize', el.tableHeight)
  },
  updated: (el, binding) => {
    if (binding.oldValue !== binding.value) {
      el.tableHeight()
    }
  },
  beforeUnmount: el => {
    window.removeEventListener('resize', el.tableHeight)
  },
})

应该注意到,和vue2的自定义指令相比:

  1. 原本的inserted没了,很多函数也没了,取而代之的是mounted,beforeMounted,updated,beforeUpdated,beforeUnmount等,使用的时候要注意到这些。
  2. 另外,vue3不建议操作参数vnode,而是操作el,因为vnode包含很多额外的函数、属性,修改容易发生错误。
  3. binding中的新旧值就是value和oldValue,不再有什么arg

可以看出vue3的自定义指令设计简洁了很多,参数命名也规范了不少,我个人很喜欢

你可能感兴趣的