飞道的博客

Vue 实现在文本溢出后浮现Tooltip、及文本展开收起效果

572人阅读  评论(0)

示例: 

  •  expandable模式(默认) - 文本展开收起效果:

  
  1. <Paragraph
  2. text= "使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例"
  3. :max-lines= "1"
  4. :width= "400"
  5. />

 

 

  •  tooltip模式 - 文本使用Tooltip效果:

文本超出后,显示T​​​​​ooltip


  
  1. <Paragraph
  2. text= "使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例"
  3. :max-lines= "1"
  4. :width= "400"
  5. type= "tooltip"
  6. />

 

文本超出后,显示T​​​​​ooltip

 文本未超出,不显示T​​​​​ooltip


  
  1. <Paragraph
  2. text= "使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例"
  3. :max-lines= "3"
  4. :width= "400"
  5. type= "tooltip"
  6. />

 

文本未超出,不显示T​​​​​ooltip
  •  tooltipExpandable模式 - 文本同时使用Tooltip和展开收起效果:

  
  1. <Paragraph
  2. text= "使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例使用示例"
  3. :max-lines= "1"
  4. :width= "400"
  5. type= "tooltipExpandable"
  6. />

 

 

全部代码: 


  
  1. <template>
  2. <div ref="textOverflow" class="text-overflow" :style="boxStyle">
  3. <el-tooltip v-bind="tooltipAttrs" :disabled="!(type === 'tooltip' || type === 'tooltipExpandable') || expanded || !isCutOut" :content="text">
  4. <span ref="overEllipsis" :title="!(type === 'tooltip' || type === 'tooltipExpandable') && text">{{ realText }} </span>
  5. </el-tooltip>
  6. <span ref="slotRef" class="slot-box">
  7. <span v-if="showSlotNode && (type === 'expandable' || type === 'tooltipExpandable')" @click="toggle">
  8. <span v-if="!expanded">{{ unfoldText }} </span>
  9. <span v-else>{{ foldText }} </span>
  10. </span>
  11. </span>
  12. </div>
  13. </template>
  14. <script>
  15. /**
  16. 使用示例:https://blog.csdn.net/qq_41887214/article/details/116663975
  17. <Paragraph
  18. :text="text"
  19. />
  20. */
  21. export default {
  22. props: {
  23. // 显示的文本
  24. text: {
  25. type: String,
  26. default: ''
  27. },
  28. // 最多展示的行数
  29. maxLines: {
  30. type: Number,
  31. default: 3
  32. },
  33. // 组件宽
  34. width: {
  35. type: Number,
  36. default: 0
  37. },
  38. // 展开
  39. unfoldText: {
  40. type: String,
  41. default: '展开'
  42. },
  43. // 收起
  44. foldText: {
  45. type: String,
  46. default: '收起'
  47. },
  48. // 是否使用Tooltip
  49. tooltip: {
  50. type: Boolean,
  51. default: false
  52. },
  53. // 组件类型,expandable、tooltip、tooltipExpandable
  54. type: {
  55. type: String,
  56. default: 'expandable'
  57. },
  58. // el-tooltip Attributes
  59. tooltipAttrs: {
  60. type: Object,
  61. default: () => {
  62. return {
  63. effect: 'dark',
  64. placement: 'top'
  65. }
  66. }
  67. }
  68. },
  69. data() {
  70. return {
  71. offset: this.text.length, // 原始文本length
  72. expanded: false, // 是否已展开
  73. slotBoxWidth: 0, // 展开收起按钮宽度
  74. textBoxWidth: this.width, // 展示的文本宽度
  75. showSlotNode: false // 是否展示slot节点
  76. }
  77. },
  78. computed: {
  79. // 设置展示文本宽度
  80. boxStyle() {
  81. if ( this.width) {
  82. return {
  83. width: this.width + 'px'
  84. }
  85. } else {
  86. return { width: 'auto' }
  87. }
  88. },
  89. // 是否被截取
  90. isCutOut() {
  91. const isCutOut = this.offset !== this.text.length
  92. return isCutOut && ! this.expanded
  93. },
  94. // 获取展示文本
  95. realText() {
  96. let realText = this.text
  97. if ( this.isCutOut) {
  98. realText = this.text.slice( 0, this.offset) + '...'
  99. }
  100. return realText
  101. }
  102. },
  103. mounted() {
  104. const { len } = this.getLines()
  105. if (len > this.maxLines) {
  106. this.showSlotNode = true
  107. this.$nextTick( () => {
  108. this.slotBoxWidth = this.$refs.slotRef.clientWidth
  109. this.textBoxWidth = this.$refs.textOverflow.clientWidth
  110. this.calculateOffset( 0, this.text.length)
  111. })
  112. }
  113. },
  114. methods: {
  115. // 计算offset 核心代码
  116. calculateOffset( from, to) {
  117. this.$nextTick( () => {
  118. if ( Math.abs( from - to) <= 1) return
  119. if ( this.isOverflow()) {
  120. to = this.offset
  121. } else {
  122. from = this.offset
  123. }
  124. this.offset = Math.floor(( from + to) / 2)
  125. this.calculateOffset( from, to)
  126. })
  127. },
  128. // 内容是否溢出
  129. isOverflow() {
  130. const { len, lastWidth } = this.getLines()
  131. if (len < this.maxLines) {
  132. return false
  133. }
  134. if ( this.maxLines) {
  135. // 超出部分 行数 > 最大行数 或者 已经是最大行数但最后一行宽度 + 后面内容超出正常宽度
  136. const lastLineOver = !!(
  137. len === this.maxLines &&
  138. lastWidth + this.slotBoxWidth > this.textBoxWidth
  139. )
  140. if (len > this.maxLines || lastLineOver) {
  141. return true
  142. }
  143. }
  144. return false
  145. },
  146. // 获取元素占据页面的所有矩形区域的行数和最后一行宽度
  147. getLines() {
  148. // getClientRects():是获取元素占据页面的所有矩形区域:
  149. const clientRects = this.$refs.overEllipsis.getClientRects()
  150. return {
  151. len: clientRects.length,
  152. lastWidth: clientRects[clientRects.length - 1].width
  153. }
  154. },
  155. // 切换展开收起
  156. toggle() {
  157. this.expanded = ! this.expanded
  158. }
  159. }
  160. }
  161. </script>
  162. <style lang="scss" scoped>
  163. @import "~@/styles/variables.scss";
  164. .slot-box {
  165. display: inline-block;
  166. cursor: pointer;
  167. color: $theme;
  168. }
  169. </style>

 


转载:https://blog.csdn.net/qq_41887214/article/details/116663975
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场