我正在开发 Vuetify 3 数据表,需要实现一个“查看更多”按钮来描述超过三行的描述。我想使用
scrollHeight
和 clientHeight
来确定文本是否被截断并提供扩展它的选项。
Vuetify Playground:Playground 链接
这是我的实现的简化版本:
<template>
<v-data-table :headers="headers" :items="items">
<template #item.description="{ item }">
<div>
<div
ref="descriptionRef"
class="three_lines_description"
:style="{ overflow: isExpanded[item.name] ? 'visible' : 'hidden' }"
>
{{ item.description }}
</div>
<v-btn
v-if="isTruncated[item.name]"
@click="toggleExpand(item.name)"
text
>
{{ isExpanded[item.name] ? 'View Less' : 'View More' }}
</v-btn>
</div>
</template>
</v-data-table>
</template>
<script>
import { ref, onMounted } from 'vue';
export default {
data() {
return {
headers: [
{ title: "Name", key: "name" },
{ title: "Email", key: "email" },
{ title: "Description", key: "description" },
],
items: [
// Sample items...
],
isExpanded: {},
isTruncated: {},
};
},
methods: {
toggleExpand(name) {
this.isExpanded[name] = !this.isExpanded[name];
},
checkTruncation() {
// Logic to check if the text is truncated...
}
},
mounted() {
this.checkTruncation();
}
};
</script>
<style scoped>
.three_lines_description {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
}
</style>
refs
来确定文本是否被截断。这是我现在代码的简化设计,仅更改
description
列的格式。在 Vuetify 数据表中实现“查看更多”功能的正确方法是什么?
如果解决方案有效,我将接受它作为答案并投票。
这是 Vue.js 3 可能的解决方案:
<script setup lang="ts">
import { ref, onMounted, nextTick } from "vue";
const headers = [
{ title: 'Name', key: 'name' },
{ title: 'Email', key: 'email' },
{ title: 'Description', key: 'description' },
];
const items = ref([
{
name: 'John Rambo',
email: '[email protected]',
description: 'This a very short description.',
showButton: false,
showButtonText: "View More",
},
{
name: 'John Doe',
email: '[email protected]',
description: 'This a short test description for the sake of testing.',
showButton: false,
showButtonText: "View More",
},
{
name: 'Jane Doe',
email: '[email protected]',
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi et nunc id augue imperdiet tempor. Duis leo nisl, aliquet et dapibus ut, eleifend sed nunc. Aenean vulputate purus tellus, ac rutrum quam mattis ac. Quisque et nunc hendrerit, pretium quam eget, dictum mauris. Aliquam pulvinar velit ac tellus porttitor, quis sagittis diam consequat. Nulla facilisi. Morbi a tempor ex. Integer tempus est ipsum, id pretium magna maximus at. Praesent finibus tempus tempus. Proin fringilla imperdiet odio eget semper. Maecenas tempus ipsum sit amet luctus tincidunt. Mauris consectetur risus in lacus placerat congue. Quisque quis arcu ut ligula finibus dapibus eu sit amet nisl. Maecenas a mi rhoncus, bibendum erat vel, pretium arcu. Vestibulum eu lectus laoreet, efficitur quam sed, ultricies risus. Morbi pharetra mauris vel venenatis lacinia.',
showButton: false,
showButtonText: "View More",
},
{
name: 'Random Guy',
email: '[email protected]',
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi et nunc id augue imperdiet tempor. Duis leo nisl, aliquet et dapibus ut, eleifend sed nunc. Aenean vulputate purus tellus, ac rutrum quam mattis ac. Quisque et nunc hendrerit, pretium quam eget, dictum mauris. Aliquam pulvinar velit ac tellus porttitor, quis sagittis diam consequat. Nulla facilisi. Morbi a tempor ex. Integer tempus est ipsum, id pretium magna maximus at. Praesent finibus tempus tempus. Proin fringilla imperdiet odio eget semper. Maecenas tempus ipsum sit amet luctus tincidunt. Mauris consectetur risus in lacus placerat congue. Quisque quis arcu ut ligula finibus dapibus eu sit amet nisl. Maecenas a mi rhoncus, bibendum erat vel, pretium arcu. Vestibulum eu lectus laoreet, efficitur quam sed, ultricies risus. Morbi pharetra mauris vel venenatis lacinia.',
showButton: false,
showButtonText: "View More",
},
]);
const descriptionRefs = ref([]);
function increaseSize(index: number) {
const divElement: HTMLDivElement = descriptionRefs.value[index];
if (divElement.dataset.expanded === "true") {
nextTick(() => {
divElement.dataset.expanded = "false"
divElement.classList.add('three_lines_description');
items.value[index].showButtonText = "View More";
})
return;
}
nextTick(() => {
divElement.dataset.expanded = "true"
divElement.dataset.showButton = "true"
divElement.classList.remove("three_lines_description");
items.value[index].showButtonText = "Show less";
});
}
function checkIfNeedsButton() {
descriptionRefs.value.forEach((item: HTMLDivElement, index) => {
if (item.scrollHeight > item.clientHeight) {
items.value[index].showButton = true;
}
});
}
onMounted(() => {
nextTick(() => {
checkIfNeedsButton();
})
});
</script>
<template>
<v-data-table :headers="headers" :items="items">
<template #item.description="{ item, index }">
<div>
<div
:ref="(el) => {
descriptionRefs.push(el);
}"
class="three_lines_description px-1 py-1"
>
{{ item.description }}
</div>
<v-btn
v-if="item.showButton"
class="mt-2 mb-2"
@click="increaseSize(index)"
>
{{ item.showButtonText }}
</v-btn>
</div>
</template>
</v-data-table>
</template>
<style scoped>
.three_lines_description {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
line-clamp: 3;
}
</style>
使用以下工具:
Vuetify Playground:示例
PD:Vuetify
中还有可扩展的 Row 功能