<template>
<div class="mm-ellipsis-container">
<div class="shadow"> <textarea :rows="rows" readonly></textarea> <div class="shadow-box" ref="box"> {{ showContent }} <slot name="ellipsis"> {{ ellipsisText }} <span class="ellipsis-btn">{{ btnText }}</span> </slot> <span ref="tail"></span> </div></div><div class="real-box"> {{ showContent }} <slot name="ellipsis" v-if="(textLength < content.length) || btnShow"> {{ ellipsisText }} <span class="ellipsis-btn" @click="clickBtn">{{ btnText }}</span> </slot></div>
</div>
</template>
<script>
import resizeObserver from 'element-resize-detector'
const observer = resizeObserver()
export default {
props: {
content: { type: String, default: ''},btnText: { type: String, default: '开展'},ellipsisText: { type: String, default: '...'},rows: { type: Number, default: 3},btnShow: { type: Boolean, default: false},
},
data () {
return { textLength: 0, beforeRefresh: null, boxWidth: 0, boxHeight: 0}
},
computed: {
showContent () { const length = this.beforeRefresh ? this.content.length : this.textLength return this.content.substr(0, this.textLength)},watchData () { return [this.content, this.btnText, this.ellipsisText, this.rows, this.btnShow]}
},
watch: {
watchData: { immediate: true, handler () { this.refresh() }},
},
mounted () {
observer.listenTo(this.$refs.box, (el) => { if (el.offsetWidth == this.boxWidth && el.offsetHeight == this.boxHeight) return this.boxWidth = el.offsetWidth this.boxHeight = el.offsetHeight this.refresh()})
},
beforeDestroy () {
observer.uninstall(this.$refs.box)
},
methods: {
refresh () { this.beforeRefresh && this.beforeRefresh() let stopLoop = false this.beforeRefresh = () => stopLoop = true this.textLength = this.content.length const checkLoop = (start, end) => { if (stopLoop || start + 1 >= end) { this.beforeRefresh = null return } const boxRect = this.$refs.box.getBoundingClientRect() const tailRect = this.$refs.tail.getBoundingClientRect() const overflow = tailRect.bottom > boxRect.bottom overflow ? (end = this.textLength) : (start = this.textLength) this.textLength = Math.floor((start + end) / 2) this.$nextTick(() => checkLoop(start, end)) } this.$nextTick(() => checkLoop(0, this.textLength))},clickBtn (event) { this.$emit('click-btn', event)},
}
}
</script>
<style lang="stylus" scoped>
.mm-ellipsis-container
text-align left
position relative
line-height 1.5
.shadow
width 100%display flexpointer-events noneopacity 0user-select noneposition absoluteoutline green solid 1pxtextarea border none flex auto padding 0 resize none overflow hidden font-size inherit line-height inherit outline none.shadow-box position absolute left 0 right 0 top 0 bottom 0
.ellipsis-btn
cursor pointertext-decoration underlinecolor #4791ff
</style>