vue利用指令实现快速设置元素的高度
作者:pe7er
在项目中经常有需要将列表的高度设置成剩余可视区域的高度,一般的做法是用ref获取后,计算元素的top,然后通过v-bind()
将top注入到style中
cn.vuejs.org/api/sfc-css-features.html#v-bind-in-css
height: calc(100vh - v-bind(top))
下面介绍一种通过指令和css变量的方式快速设置列表高度的方法,下面是代码示例。
import type { DirectiveBinding, Directive } from 'vue' const PREFIX = '--bounding-info-' interface IOptions { prefix?: string } const setStyles = (el: HTMLElement, options: IOptions = {}) => { const { prefix = PREFIX } = options const boundingClientRectInfo = el.getBoundingClientRect() const { width, height, top, right, bottom, left, x, y } = boundingClientRectInfo const rawStylesStr = el.getAttribute('style') const rawStyles = rawStylesStr ? rawStylesStr.split(';').filter((item) => !!item && !item.includes(prefix)) : [] const bindingStyles = [ { name: 'width', value: width }, { name: 'height', value: height }, { name: 'top', value: top }, { name: 'right', value: right }, { name: 'bottom', value: bottom }, { name: 'left', value: left }, { name: 'x', value: x }, { name: 'y', value: y } ].map((item) => `${prefix}${item.name}: ${item.value}px`) const newStyles = rawStyles.concat(bindingStyles) el.setAttribute('style', newStyles.join(';')) } const boundingInfoToCssVar: Directive = { mounted(el: HTMLElement, binding: DirectiveBinding) { setStyles(el, binding.arg as IOptions) }, updated(el: HTMLElement, binding: DirectiveBinding, vnode, prevVnode) { setStyles(el, binding.arg as IOptions) } // beforeUnmount(el: HTMLElement, binding: DirectiveBinding) { // console.log(el) // } } export const name = 'BoundingInfoToCssVar' export default boundingInfoToCssVar
使用方法
<div v-if="activated" v-bounding-info-to-css-var:[boundingInfoOptions] style="font-size: 12px" :style="styles" @click="closeHandle" class="overflow" /> <script lang="ts" setup> const boundingInfoOptions = { prefix: '--bounding-info-' } </script> <style lang="less"> .overflow { height: calc(100vh - var(--bounding-info-top)); } </style>
这是一个使用 Vue.js 实现的指令,它将元素的边界信息转换为 CSS 变量,并将这些 CSS 变量应用到元素的样式上。
以下是代码的详细解释:
setStyles
函数用于设置元素的样式。它接受一个元素和一个可选的配置对象作为参数。配置对象可以包含一个前缀选项,用于指定生成的 CSS 变量的前缀。
- 函数内部首先获取元素的边界信息,包括宽度、高度、上边界、右边界、下边界、左边界、水平偏移量和垂直偏移量。
- 然后,它从元素的现有样式中提取出不包含指定前缀的样式,并将其存储在
rawStyles
数组中。 - 接下来,它根据边界信息生成一组 CSS 变量,并将其存储在
bindingStyles
数组中。每个 CSS 变量的名称都以指定的前缀开头,后面跟着对应的边界信息名称,值为边界信息的值,单位为像素。 - 最后,它将原始样式和生成的绑定样式合并成一个新的样式字符串,并将其设置回元素的
style
属性中。
boundingInfoToCssVar
指令用于将边界信息转换为 CSS 变量。它包含mounted
和updated
两个生命周期钩子函数。
mounted
函数在指令首次绑定到元素时被调用,它调用setStyles
函数来设置元素的样式。updated
函数在指令的绑定值发生变化时被调用,它也调用setStyles
函数来更新元素的样式。
代码最后导出了指令的名称和定义,以便在其他地方使用。
使用这个指令时,可以在模板中使用v-bounding-info-css-var
指令来绑定一个对象,该对象可以包含一个prefix
选项,用于指定 CSS 变量的前缀。例如:
<!-- 此处的元素将具有带有 --my-prefix- 前缀的 CSS 变量 --> <div v-bounding-info-css-var="{ prefix: '--my-prefix-' }"></div>
这样,元素的边界信息将被转换为带有指定前缀的 CSS 变量,并应用到元素的样式上。
这段代码是一个使用 Vue.js 的示例,它包含一个具有条件渲染和一个自定义指令 v-bounding-info-to-css-var
的 <div>
元素。下面是代码的详细解释:
<div v-if="activated" v-bounding-info-to-css-var:[boundingInfoOptions] style="font-size: 12px" :style="styles" @click="closeHandle" class="list" />
v-if="activated"
:这是一个条件渲染指令,只有当activated
变量的值为true
时,这个<div>
元素才会被渲染。v-bounding-info-to-css-var:[boundingInfoOptions]
:这是一个自定义指令,它接受一个参数boundingInfoOptions
,这个参数会被传递给指令的处理函数。style="font-size: 12px"
:这是一个内联样式,用于设置<div>
元素的字体大小为12px
。:style="styles"
:这是一个 v-bind 指令,它将styles
变量绑定到<div>
元素的style
属性上。@click="closeHandle"
:这是一个事件监听指令,当点击<div>
元素时,会触发closeHandle
函数。class="list"
:这是一个类名,用于给<div>
元素添加一个名为list
的类。
const boundingInfoOptions = { prefix: '--bounding-info-' }
boundingInfoOptions
:这是一个对象,它包含了自定义指令 v-bounding-info-to-css-var
所需的参数。在这个例子中,prefix
是一个参数,它的值为 --bounding-info-
。
.list { height: calc(100vh - var(--bounding-info-top)); }
.list
:这是一个类选择器,用于选择具有 list
类的元素。
height: calc(100vh - var(--bounding-info-top));
:这是一个 CSS 样式声明,它使用了 calc
函数来计算元素的高度。100vh
表示视窗的高度,var(--bounding-info-top)
表示一个变量,它的值是由自定义指令 v-bounding-info-to-css-var
设置的上边界距离。通过减去上边界的距离,得到了元素的高度。
总的来说,这段代码的目的是在一个具有特定条件(activated
为 true
)的情况下,渲染一个 <div>
元素。这个元素具有一些样式,并且当点击时会触发一个函数。此外,它还使用了一个自定义指令来将元素的边界信息转换为 CSS 变量,并使用这些变量来设置元素的样式。
到此这篇关于vue利用指令实现快速设置元素的高度的文章就介绍到这了,更多相关vue指令设置元素高度内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!