v-boxresize 指令
介绍
v-boxresize
指令主要作用是监听元素的尺寸变化,并在尺寸变化时触发回调函数。
使用方法
将 v-boxresize
指令添加到需要支持复制功能的元素上:
vue
<template>
<div v-boxresize="{ callback: handleResize, box: string }">Resize me!</div>
</template>
基本用法(响应式布局)
调整窗口大小试试
当前布局:大屏布局
查看代码
vue
<template>
<div class="resize-container">
<div v-boxresize="{ callback: onResize, box: 'content-box' }" class="resize-box">调整窗口大小试试</div>
<p class="hint-text">当前布局:{{ layout }}</p>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { vBoxResize } from '@cp-vuedir/core'
const layout = ref('大屏布局')
const onResize = (rect: DOMRectReadOnly, box: string) => {
if (rect.width < 600) {
layout.value = '小屏布局'
} else {
layout.value = '大屏布局'
}
}
</script>
<style scoped>
.resize-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 80vh;
background-color: var(--vp-c-bg-soft);
font-family: 'Arial', sans-serif;
padding: 20px;
}
.resize-box {
width: 100%;
height: 600px;
display: flex;
align-items: center;
justify-content: center;
background-color: #42b983;
color: white;
font-size: 20px;
font-weight: bold;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
transition:
background-color 0.3s ease,
transform 0.3s ease;
}
.resize-box:hover {
background-color: #369c6d;
transform: scale(1.05);
}
.hint-text {
margin-top: 20px;
font-size: 18px;
color: var(--vp-c-text-3);
background-color: var(--vp-c-bg-soft);
padding: 10px 20px;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
</style>
图表自适应
当前缩放比例: 1.00
查看代码
vue
<template>
<div class="chart-wrapper">
<div v-boxresize="{ callback: onResize }" class="chart-container">
<div v-for="(value, index) in data" :key="index" class="bar" :style="{ height: value * scale + 'px' }">
<span class="bar-label">{{ value }}</span>
</div>
</div>
<p class="scale-text">当前缩放比例: {{ scale.toFixed(2) }}</p>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { vBoxResize } from '@cp-vuedir/core'
const data = ref([10, 20, 30, 40, 50])
const scale = ref(1)
const onResize = (rect: DOMRectReadOnly) => {
scale.value = rect.width / 500
}
</script>
<style scoped>
.chart-wrapper {
width: 100%;
height: 300px;
border: 1px solid #ddd;
border-radius: 10px;
background-color: var(--vp-c-bg-soft);
box-shadow: 0 4px 6px rgba(0, 0, 0, 1);
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 20px;
}
.chart-container {
display: flex;
align-items: flex-end;
justify-content: space-around;
width: 100%;
height: 80%;
padding: 20px;
background-color: var(--vp-c-bg);
border-radius: 10px;
}
.bar {
width: 40px;
background-color: #42b983;
margin: 0 5px;
border-radius: 5px 5px 0 0;
transition:
height 0.3s ease,
background-color 0.3s ease;
position: relative;
}
.bar:hover {
background-color: #369c6d;
}
.bar-label {
position: absolute;
bottom: -25px;
left: 50%;
transform: translateX(-50%);
font-size: 14px;
color: var(--vp-c-text-3);
font-weight: bold;
}
.scale-text {
margin-top: 10px;
font-size: 16px;
color: var(--vp-c-text-3);
font-weight: bold;
background-color: var(--vp-c-bg);
padding: 10px 20px;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
@media (max-width: 600px) {
.bar {
width: 30px;
}
.bar-label {
font-size: 12px;
}
.scale-text {
font-size: 14px;
}
}
</style>
自适应图片
查看代码
vue
<template>
<div>
<div v-boxresize="{ callback: onResize }" class="image-container">
<img :src="imageUrl" :style="imageStyle" alt="自适应图片" class="responsive-image" />
<div class="image-overlay">
<p class="image-text">自适应图片示例</p>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { vBoxResize } from '@cp-vuedir/core'
const imageUrl = 'https://picsum.photos/800/400?random=6'
const imageStyle = ref({})
const onResize = (rect: DOMRectReadOnly) => {
if (rect.width < 400) {
imageStyle.value = { width: '100%', height: 'auto' } // 小屏:宽度 100%,高度自适应
} else {
imageStyle.value = { width: 'auto', height: '100%' } // 大屏:高度 100%,宽度自适应
}
}
</script>
<style scoped>
/* 图片容器样式 */
.image-container {
width: 100%;
height: 300px;
border: 1px solid #ddd;
border-radius: 10px;
overflow: hidden;
position: relative;
background-color: var(--vp-c-bg-soft);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
/* 自适应图片样式 */
.responsive-image {
display: block;
transition:
transform 0.3s ease,
filter 0.3s ease;
}
/* 图片悬停效果 */
.image-container:hover .responsive-image {
transform: scale(1.05);
filter: brightness(0.8);
}
/* 图片遮罩样式 */
.image-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
}
/* 遮罩悬停效果 */
.image-container:hover .image-overlay {
opacity: 1;
}
/* 图片文字样式 */
.image-text {
color: white;
font-size: 24px;
font-weight: bold;
text-align: center;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
}
/* 响应式调整 */
@media (max-width: 400px) {
.image-text {
font-size: 18px;
/* 小屏时字体减小 */
}
}
</style>
改变页面元素尺寸,自适应字体大小
测试文本,根据容器宽度动态调整字体大小。
查看代码
vue
<template>
<div v-boxresize="{ callback: onResize }" class="resize-container">
<p :style="{ fontSize: fontSize + 'px' }" class="dynamic-text">测试文本,根据容器宽度动态调整字体大小。</p>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { vBoxResize } from '@cp-vuedir/core'
const fontSize = ref(16)
const onResize = (rect: DOMRectReadOnly) => {
fontSize.value = Math.max(12, rect.width / 20)
}
</script>
<style scoped>
.resize-container {
width: 100%;
height: 200px;
display: flex;
align-items: center;
justify-content: center;
background-color: #42b983;
border: 1px solid #369c6d;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.resize-container:hover {
background-color: #369c6d;
}
.dynamic-text {
color: white;
font-weight: bold;
text-align: center;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
}
@media (max-width: 600px) {
.dynamic-text {
font-size: 18px !important;
}
}
</style>
表单自适应
列 1 | 列 2 | 列 3 |
---|---|---|
数据 1 | 数据 2 | 数据 3 |
数据 4 | 数据 5 | 数据 6 |
数据 7 | 数据 8 | 数据 9 |
查看代码
vue
<template>
<div v-boxresize="{ callback: onResize }" class="table-container">
<table class="dynamic-table">
<thead>
<tr>
<th :style="{ width: columnWidths[0] + 'px' }">列 1</th>
<th :style="{ width: columnWidths[1] + 'px' }">列 2</th>
<th :style="{ width: columnWidths[2] + 'px' }">列 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>数据 1</td>
<td>数据 2</td>
<td>数据 3</td>
</tr>
<tr>
<td>数据 4</td>
<td>数据 5</td>
<td>数据 6</td>
</tr>
<tr>
<td>数据 7</td>
<td>数据 8</td>
<td>数据 9</td>
</tr>
</tbody>
</table>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { vBoxResize } from '@cp-vuedir/core'
const columnWidths = ref([100, 150, 200]) // 初始列宽
const onResize = (rect: DOMRectReadOnly) => {
const totalWidth = rect.width
columnWidths.value = [totalWidth * 0.3, totalWidth * 0.4, totalWidth * 0.3]
}
</script>
<style scoped>
.table-container {
width: 100%;
overflow-x: auto;
border: 1px solid var(--vp-c-text-1);
background-color: var(--vp-c-bg-soft);
color: var(--vp-c-text-1);
}
.dynamic-table {
width: 100%;
border-collapse: collapse;
}
.dynamic-table th {
background-color: var(--vp-c-bg-1);
font-weight: bold;
padding: 12px;
text-align: left;
border-bottom: 2px solid var(--vp-c-text-1);
}
.dynamic-table td {
padding: 10px;
border-bottom: 1px solid #ddd;
}
.dynamic-table tr:hover {
background-color: #f5f5f5;
}
@media (max-width: 600px) {
.dynamic-table th,
.dynamic-table td {
padding: 8px;
}
}
</style>
API
属性名 | 说明 | 类型 | 是否必选 | 默认值 |
---|---|---|---|---|
callback | 页面尺寸变化时的回调函数 | (rect: DOMRectReadOnly, box?: string) => void | null | |
box | 盒模型类型 | string | content-box |
注意事项
提示
v-resize
指令在页面加载时不会立即触发回调函数,只有在元素尺寸发生变化时才会触发。- 上面示例中都需要改变浏览器窗口大小才能触发回调函数,看到具体效果。
注意浏览器兼容
- 需要浏览器支持
ResizeObserver API
- 对于
box
属性,不同浏览器对盒模型的支持可能有所不同,这里默认使用的是content-box
,如果需要使用其他盒模型,请根据实际情况添加box API
。 - 可支持的盒模型类型有:
border-box
|content-box
|device-pixel-content-box
。