在项目中经常有需要将列表的高度设置成剩余可视区域的高度,一般的做法是用ref获取后,计算元素的top,然后通过v-bind()
将top注入到style中
css
height: calc(100vh - v-bind(top))
下面介绍一种通过指令和css变量的方式快速设置列表高度的方法,下面是代码示例。
ts
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
使用方法
html
<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 变量的前缀。例如:
html
<!-- 此处的元素将具有带有 --my-prefix- 前缀的 CSS 变量 -->
<div v-bounding-info-css-var="{ prefix: '--my-prefix-' }"></div>
这样,元素的边界信息将被转换为带有指定前缀的 CSS 变量,并应用到元素的样式上。
这段代码是一个使用 Vue.js 的示例,它包含一个具有条件渲染和一个自定义指令 v-bounding-info-to-css-var
的 <div>
元素。下面是代码的详细解释:
html
<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
的类。
js
const boundingInfoOptions = { prefix: '--bounding-info-' }
boundingInfoOptions
:这是一个对象,它包含了自定义指令v-bounding-info-to-css-var
所需的参数。在这个例子中,prefix
是一个参数,它的值为--bounding-info-
。
css
.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 变量,并使用这些变量来设置元素的样式。
以上代码作者编写,大部分文字和少部分代码由coze生成。