当前位置:   article > 正文

CSS+JS+Vue:单行、多行文本溢出显示省略号...的几种实现方式_单行文本溢出

单行文本溢出

背景:近期H5项目有个UI需求,单行文本超长时,超出的部分...省略且有一个查看的图标;否则正常展示。

在此背景下了总结下文本溢出的几种实现方式。

1、单行文本溢出【纯css】

效果:

  1. <!--html-->
  2. <div class="text-ellipsis">一些随机文字,一二三四五六七八九十。超长测试文本1234567890。</div>
  3. <!--css-->
  4. .text-ellipsis {
  5. width: 200px;
  6. white-space: nowrap;
  7. overflow: hidden;
  8. text-overflow: ellipsis;
  9. }

2、多行文本溢出【纯css】

效果:

  1. <!--html-->
  2. <div class="text-ellipsis-two">一些随机文字,一二三四五六七八九十。超长测试文本1234567890。</div>
  3. <!--css-->
  4. .text-ellipsis-two {
  5. width: 200px;
  6. overflow: hidden;
  7. text-overflow: ellipsis;
  8. display: -webkit-box;
  9. -webkit-line-clamp: 2;
  10. -webkit-box-orient: vertical;
  11. }

看效果已实现,但略一思索-webkit-前缀,怕不是有兼容性问题。如你所想,它有。需要兼容IE的童鞋,请彻底放弃这种写法,具体参见caniuse

单纯的依靠CSS想要定制多行文本溢出展示有难度,有没有封装好的组件直接用,于是就有了第三种实现方式。

3、HeyUI组件库:TextEllipsis 超出文本省略

效果:

  1. <!--html-->
  2. <!--例一-->
  3. <TextEllipsis :text="txt1" :height="50" v-width="200">
  4. <template slot="more">...</template>
  5. </TextEllipsis>
  6. <!--例二-->
  7. <TextEllipsis :text="txt1" :height="50" v-width="200" :isLimitHeight="isLimitH" >
  8. <template slot="more"><span>...</span><span @click="isLimitH=false">查看更多</span></template>
  9. <span slot="after" v-if="!isLimitH" @click="isLimitH=true">收起</span>
  10. </TextEllipsis>
  11. <!--data-->
  12. txt1: '一些随机文字,一二三四五六七八九十。超长测试文本1234567890。',
  13. isLimitH: true

例一即可实现方式二中的效果。

例二中自定义更多,文本超长时,溢出部分...省略,且展示查看更多按钮;点击查看更多,超长文本全部展示且有收起按钮,点击收起按钮,回到...状态。文本未超长时,正常展示。

挑战部分,Vue项目怎么写一个类似组件?来往下看,方式四来了。

4、仿HeyUI的TextEllipsis组件【Vue+CSS+JS】

效果:

  1. // 父组件
  2. <!--template-->
  3. <textE :text="txt1" :height="50" v-width="200">
  4. <template slot="more">...</template>
  5. </textE>
  6. <textE :text="txt2" :height="50" v-width="200">
  7. <template slot="more">...</template>
  8. </textE>
  9. <textE :text="txt1" :height="50" v-width="200" :isLimitHeight="isLimitHeight">
  10. <template slot="more"><span>...</span><span class="link" @click="isLimitHeight=false">查看更多</span></template>
  11. <span slot="after" class="link" v-if="!isLimitHeight" @click="isLimitHeight=true">收起</span>
  12. </textE>
  13. <!--script-->
  14. import textE from './textellipsisComponent'
  15. export default {
  16. components: {textE},
  17. data () {
  18. return {
  19. isLimitHeight: true,
  20. txt1: '一些随机文字,一二三四五六七八九十。超长测试文本1234567890。',
  21. txt2: '111'
  22. }
  23. }
  24. }
  1. // 子组件 textellipsisComponent.vue
  2. <template>
  3. <div>
  4. <span>
  5. <span class="limit-text">{{text}}</span><!--
  6. --><span class="more"><slot name="more"></slot></span><!--
  7. --><slot name="after"></slot>
  8. </span>
  9. </div>
  10. </template>
  11. <script>
  12. export default {
  13. inheritAttrs: false,
  14. props: {
  15. height: Number,
  16. text: String,
  17. isLimitHeight: {
  18. type: Boolean,
  19. default: true
  20. }
  21. },
  22. data () {
  23. return {
  24. }
  25. },
  26. watch: {
  27. text () {
  28. this.init()
  29. },
  30. isLimitHeight () {
  31. this.init()
  32. }
  33. },
  34. mounted () {
  35. this.init()
  36. },
  37. methods: {
  38. init () {
  39. let title = this.$el
  40. let textDom = this.$el.querySelector('.limit-text')
  41. let more = this.$el.querySelector('.more')
  42. more.style.display = 'none'
  43. this.$nextTick(() => {
  44. if (this.isLimitHeight) {
  45. if (title.scrollHeight > this.height) {
  46. more.style.display = 'inline-block'
  47. let text = this.text
  48. let n = 1000
  49. while (title.scrollHeight > this.height && n > 0) {
  50. if (title.scrollHeight > this.height * 3) {
  51. textDom.innerText = text = text.substring(0, Math.floor(text.length / 2))
  52. } else {
  53. textDom.innerText = text = text.substring(0, text.length - 1)
  54. }
  55. n--
  56. }
  57. }
  58. } else {
  59. textDom.innerText = this.text
  60. }
  61. })
  62. }
  63. }
  64. }
  65. </script>
  66. <style scoped>
  67. </style>

核心逻辑是:计算节点的scrollHeight和预期高度height进行比较,做相应处理。

5、跟着element-ui实现单行文本溢出【Vue+CSS+JS】

table中单元格有个show-overflow-tooltip属性,作用是当内容过长被隐藏时显示 tooltip。此组件仅支持单行文本,且超出部分省略仅支持...,不支持自定义。

效果:

  1. // 父组件
  2. <!--template-->
  3. <tooltips :txt="txt1" showOverflow></tooltips>
  4. <tooltips :txt="txt2" showOverflow></tooltips>
  5. <!--script-->
  6. import tooltips from './tooltips'
  7. export default {
  8. components: {tooltips},
  9. data () {
  10. return {
  11. txt1: '一些随机文字,一二三四五六七八九十。超长测试文本1234567890。',
  12. txt2: '111'
  13. }
  14. }
  15. }
  1. // 子组件 tooltips.vue
  2. <template>
  3. <div>
  4. <div class="flex">
  5. <div ref="cell" class="cell">{{txt}}</div>
  6. <div class="img" v-show="showFlag"></div>
  7. </div>
  8. </div>
  9. </template>
  10. <script>
  11. export default {
  12. props: {
  13. txt: String, // 超长字符串
  14. showOverflow: { // 当内容过长被隐藏时显示tip
  15. type: Boolean,
  16. default: false
  17. }
  18. },
  19. data () {
  20. return {
  21. showFlag: false
  22. }
  23. },
  24. watch: {
  25. txt (val) {
  26. if (!val || !this.showOverflow) return
  27. this.$nextTick(() => {
  28. this.calcTextWidth()
  29. })
  30. }
  31. },
  32. mounted () {
  33. if (this.showOverflow) {
  34. this.$nextTick(() => {
  35. this.calcTextWidth()
  36. })
  37. }
  38. },
  39. methods: {
  40. calcTextWidth () {
  41. const cellNode = this.$el.querySelector('.cell')
  42. const range = document.createRange()
  43. range.setStart(cellNode, 0)
  44. range.setEnd(cellNode, cellNode.childNodes.length)
  45. const rangeWidth = range.getBoundingClientRect().width
  46. let computed = document.defaultView.getComputedStyle(cellNode, '')
  47. let paddingLeft = parseInt(computed['paddingLeft']) || 0 // computed['paddingLeft']结果是:'10px'
  48. let paddingRight = parseInt(computed['paddingRight']) || 0 // computed['paddingLeft']结果是:'4px'
  49. const padding = paddingLeft + paddingRight
  50. // Element.offsetWidth属性返回一个整数,表示元素的 CSS 水平宽度(单位像素),包括元素本身的高度、padding 和 border,以及垂直滚动条的宽度(如果存在滚动条)
  51. // Element.scrollWidth 属性返回一个整数值(小数会四舍五入),表示当前元素的总宽度(单位像素),包括溢出容器、当前不可见的部分。它包括padding,但是不包括border、margin以及水平滚动条的宽度(如果有垂直滚动条的话),还包括伪元素(::before::after)的宽度。
  52. if (rangeWidth + padding > cellNode.offsetWidth || cellNode.scrollWidth > cellNode.offsetWidth) {
  53. this.showFlag = true
  54. } else {
  55. this.showFlag = false
  56. }
  57. }
  58. }
  59. }
  60. </script>
  61. <style scoped>
  62. .flex {
  63. width: 300px;
  64. display: flex;
  65. flex-direction: row;
  66. align-items: center;
  67. }
  68. .cell {
  69. overflow: hidden;
  70. text-overflow: ellipsis;
  71. white-space: nowrap;
  72. padding-left: 10px;
  73. padding-right: 4px;
  74. flex: 1;
  75. }
  76. .img {
  77. width: 16px;
  78. height: 16px;
  79. background-color: deepskyblue;
  80. }
  81. </style>

The end

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号