<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>