TextClamp
使用 js 实现文本展开、收起,并非纯 CSS 实现。
Props:
- fontSize:Number,默认:14
- lines:Number,默认:1
- lineHeight:Number,默认:20
Feat:
- 监听插槽的变化(文本内容的变化),自动计算文本高度
- 展开、折叠时有 transition 效果
- 文本内容较少时(未超过行数 lines),不会展示按钮
Code
text-clamp.vue
<template><div class="text-clamp"><div class="text" :style="{height}"><span v-if="isVisible" class="btn" @click="toggle">{{isExpand ? '收起' : '... 展开'}}</span><div ref="textRef" :style="commonStyle"><slot /></div></div></div>
</template><script>
export default {name: "TextClamp",props: {fontSize: {type: Number,default: 14},lines: {type: Number,default: 1},lineHeight: {type: Number,default: 20},selectors: {type: String,default: ""}},data () {return {isExpand: false,isVisible: false,textHeight: 0}},computed: {height () {if (this.isExpand) {return this.$refs.textRef.clientHeight + 'px';} else {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: 12px;line-height: 14px;padding: 2px 6px;background: #1890ff;border-radius: 2px;color: #fff;cursor: pointer;
}
</style>
实例
<div style="min-height: 120px;"><text-clamp :lines="6">123123</text-clamp>
</div>
<text-clamp :lines="5" :line-height="24">{{data || "--"}}</text-clamp>