父组件

import ShowMore from ‘@/components/ShowMore.vue’;

1
2
3
<show-more :show-height="338">
content
</show-more>

子组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<template>
<div class="wrapper-container">
<!-- overflow: hidden:清除子元素相对父元素的超界溢出 -->
<div
style="overflow: hidden"
:style="{
height: showMore ? 'auto' : showHeight + 'px',
}"
>
<div ref="contentRef">
<slot>
<!-- 当外界 <show-more> 标签中有元素时,使用 <show-more> 标签中的元素进行渲染,否则使用下面这个 div 进行渲染 -->
<div v-html="content"></div>
</slot>
</div>
</div>
<div
v-show="isLongContent"
class="control"
:class="{ 'show-more': showMore }"
>
<div class="btn" @click="_toggleShowMore">
{{ showMore ? '收起' : '展开' }}
</div>
</div>
</div>
</template>

<script setup>
import { ref, onUpdated } from 'vue';
const props = defineProps({
showHeight: {
type: Number,
required: true,
default: 400,
},
content: {
type: String,
default: null,
},
});
const contentRef = ref(null);
const showMore = ref(false);
const isLongContent = ref(false);
const initLongContent = () => {
if (!contentRef.value) {
return;
}
const contentHeight = contentRef.value.clientHeight;
isLongContent.value = contentHeight > props.showHeight;
};
onUpdated(() => {
initLongContent();
});
const _toggleShowMore = () => {
showMore.value = !showMore.value;
};
</script>
<style scoped lang="scss">
.wrapper-container {
position: relative;
margin-bottom: 24px;
padding-bottom: 20px;
.control {
position: absolute;
bottom: 0;
width: 100%;
padding-top: 56px;
background: linear-gradient(
359deg,
rgba(255, 255, 255, 0.9) 0%,
rgba(255, 255, 255, 0.28) 100%
);
.btn {
font-size: 14px;
font-weight: 500;
color: #24bffb;
text-align: center;
margin-bottom: 20px;
}
&.show-more {
padding-top: 0;
background: #fff;
}
}
}
</style>