#### 1 为什么会有这个需求呢?
在日常前端开发中,希望表格能够自适应不同的屏幕的大小高度,同时页面进行缩放的同时,表格也需要进行同时适配不同的屏幕大小,下面以elementuiPlus组件的table表格为例子。
简单介绍一下vue3的自定义指令是什么;官方文档的介绍是除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之外,Vue 还允许你注册自定义的指令 (Custom Directives)。自定义指令主要是为了重用涉及普通元素的底层 DOM 访问的逻辑。说的简单点,就是通过一个指令参数去修改你DOM行为
本文主要是针对vue3开发而写的,首先我们需要引入App,vue3的挂载都是在App上的,然后创建一个指令并默认导出,resize是指令的名称,resizeHeightDirective是实现指令的方法
```html
import type { App } from 'vue'
// 创建Vue应用实例
// 注册自定义指令
export function resize(app: App<Element>) {
app.directive('resize', resizeHeightDirective)
}
```
这是resizeHeightDirective方法的实现
```html
const resizeHeightDirective = {
mounted(el, binding) {
// 为元素添加自定义属性来存储resize事件监听器
el.resizeListener = () => {
setHeight(el, binding)
}
// 初始设置高度
setHeight(el, binding)
// 监听窗口resize事件
window.addEventListener('resize', el.resizeListener)
},
unmounted(el: { resizeListener: (this: Window, ev: UIEvent) => any }) {
// 移除窗口resize事件监听器
window.removeEventListener('resize', el.resizeListener)
}
}
// 设置元素高度
function setHeight(
el: { offsetTop: any; style: { height: string } },
binding: { value: { bottom: number } }
) {
const top = el.offsetTop
const bottom = binding.value?.bottom || 64
const pageHeight = window.innerHeight - 140
el.style.height = `${pageHeight - top - bottom}px`
}
```
其实也就是在每次在mounted里面屏幕监听到高度的改变,然后重新设置dom元素的高度,setHeight就是设置高度的方法,top和bottom都可以根据自己开发的页面边距进行调整。
然后在全局挂载加载这个指令,就可以使用了, 我这里多封装了一层,放在了Directive文件夹下,方便后续文档管理
```html
import type { App } from 'vue'
import { resize } from './permission/tableResize'
/**
* 导出指令:v-xxx
*/
export const setupAuth = (app: App<Element>) => {
resize(app)
}
```
```html
// 路由
import router, { setupRouter } from '@/router'
// 这里引入全局指令
import { setupAuth } from '@/directives'
import { createApp } from 'vue'
import App from './App.vue'
// 创建实例
const setupAll = async () => {
const app = createApp(App)
await setupI18n(app)
setupStore(app)
setupElementPlus(app)
setupFormCreate(app)
//这里注册使用就行
setupRouter(app)
setupAuth(app)
app.mount('#app')
}
setupAll()
```
最后去对应的页面使用v-resize指令就可以实现啦
![](https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=27d370b5ecb6fb45767d5b7b863fc80f&file=file.png)