<template>
<div class="text-clamp">
<div class="text" :style="{ height }">
<span v-if="isVisible" class="btn" @click.stop="toggle">
<template v-if="!isExpand">
<span class="ellipsis">... </span>
<span>展开</span>
</template>
<template v-else>
<span>收起</span>
</template>
</span>
<div ref="textRef" :style="commonStyle">
<slot />
</div>
</div>
</div>
</template>
<script>
export default {
name: "TextClamp",
props: {
fontSize: {
type: String,
default: "16",
},
lines: {
type: String,
default: "1",
},
lineHeight: {
type: String,
default: "22",
},
selectors: {
type: String,
default: "",
},
},
data() {
return {
isExpand: false,
isVisible: false,
textHeight: 0,
};
},
computed: {
height() {
if (this.isExpand) {
return this.$refs.textRef.clientHeight + "px";
}
return Math.min(this.lines * this.lineHeight, this.textHeight) + "px";
},
commonStyle() {
return {
lineHeight: this.lineHeight + "px",
fontSize: this.fontSize + "px",
};
},
},
mounted() {
this.init();
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === "characterData") {
this.init();
}
});
});
observer.observe(this.$refs.textRef, {
characterData: true,
subtree: true,
childList: true,
});
},
methods: {
init() {
this.isExpand = false;
this.textHeight = this.$refs?.textRef?.clientHeight || 0;
this.isVisible = this.textHeight > this.lines * this.lineHeight;
},
toggle() {
this.isExpand = !this.isExpand;
if (!this.isExpand && this.selectors) {
const initEl = document.querySelector(this.selectors);
setTimeout(() => {
initEl.scrollIntoView({
behavior: "smooth",
block: "start",
inline: "center",
});
}, 97);
}
},
},
};
</script>
<style lang="scss" scoped>
.text-clamp {
display: flex;
overflow: hidden;
}
.text {
font-size: 20px;
transition: 0.3s height;
}
.text::before {
content: "";
height: calc(100% - 20px);
float: right;
}
.btn {
float: right;
clear: both;
font-size: 15px;
line-height: 22px;
color: var(--text_black_lv2);
cursor: pointer;
.btn-pic {
width: 13px;
height: 13px;
margin-left: 3px;
}
}
.ellipsis {
color: var(--text_black_lv1) !important;
}
</style>