通过封装一个v-clamp的指令处理多行文本的溢出

如果下载的源码需要作者授权,请更换源码。本站免费分享资源不会增加授权

本篇文章给大家带来的内容是关于通过封装一个v-clamp的指令处理多行文本的溢出,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

最近做项目时,遇到了一个需求:要求div里文本在两行显示,div的宽度是固定的,如果溢出的话就显示省略号。单行文本的溢出问题,我们都很熟悉,只要添加以下css属性就ok:

  overflow: hidden;   white-space: nowrap; //段落中文本不换行   text-overflow: ellipsis;

但是多行文本的溢出怎么处理呢?

查了资料之后发现还是有办法的

在WebKit浏览器或移动端(绝大部分是WebKit内核的浏览器)的页面实现比较简单,可以直接使用WebKit的CSS扩展属性(WebKit是私有属性)-webkit-line-clamp ;注意:这是一个 不规范的属性(unsupported WebKit property),它没有出现在 CSS 规范草案中。-webkit-line-clamp用来限制在一个块元素显示的文本的行数。 为了实现该效果,它需要组合其他的WebKit属性。

我们用一下代码即可实现:

    overflow : hidden;     text-overflow: ellipsis;     display: -webkit-box;     -webkit-line-clamp: 2;     -webkit-box-orient: vertical;

但是这样处理会遇到兼容性问题,在Firefox浏览器上就不起作用。

为了解决兼容性问题,有一个clamp.js[https://www.npmjs.com/package…]很好的解决这个问题。

为了更好的跟Vue相结合,今天我们就封装一个v-clamp的指令,来方便的解决这个问题。

// 注册一个全局自定义指令 `v-clamp` Vue.directive('clamp', {   // 当被绑定的元素插入到 DOM 中时……   update: function (el, binding) {       function clamp(element, options) {           options = options || {};                  var self = this,             win = window,             opt = {               clamp: options.clamp || 2,               useNativeClamp: typeof(options.useNativeClamp) != 'undefined' ? options.useNativeClamp : true,               splitOnChars: options.splitOnChars || ['.', '-', '–', '—', ' '], //Split on sentences (periods), hypens, en-dashes, em-dashes, and words (spaces).               animate: options.animate || false,               truncationChar: options.truncationChar || '…',               truncationHTML: options.truncationHTML             },                    sty = element.style,             originalText = element.innerHTML,                    supportsNativeClamp = typeof(element.style.webkitLineClamp) != 'undefined',             clampValue = opt.clamp,             isCSSValue = clampValue.indexOf && (clampValue.indexOf('px') > -1 || clampValue.indexOf('em') > -1),             truncationHTMLContainer;                  if (opt.truncationHTML) {             truncationHTMLContainer = document.createElement('span');             truncationHTMLContainer.innerHTML = opt.truncationHTML;           }                         // UTILITY FUNCTIONS __________________________________________________________                  /**            * Return the current style for an element.            * @param {HTMLElement} elem The element to compute.            * @param {string} prop The style property.            * @returns {number}            */           function computeStyle(elem, prop) {             if (!win.getComputedStyle) {               win.getComputedStyle = function(el, pseudo) {                 this.el = el;                 this.getPropertyValue = function(prop) {                   var re = /(-([a-z]){1})/g;                   if (prop == 'float') prop = 'styleFloat';                   if (re.test(prop)) {                     prop = prop.replace(re, function() {                       return arguments[2].toUpperCase();                     });                   }                   return el.currentStyle && el.currentStyle[prop] ? el.currentStyle[prop] : null;                 };                 return this;               };             }                    return win.getComputedStyle(elem, null).getPropertyValue(prop);           }                  /**            * Returns the maximum number of lines of text that should be rendered based            * on the current height of the element and the line-height of the text.            */           function getMaxLines(height) {             var availHeight = height || element.clientHeight,               lineHeight = getLineHeight(element);                    return Math.max(Math.floor(availHeight / lineHeight), 0);           }                  /**            * Returns the maximum height a given element should have based on the line-            * height of the text and the given clamp value.            */           function getMaxHeight(clmp) {             var lineHeight = getLineHeight(element);             return lineHeight * clmp;           }                  /**            * Returns the line-height of an element as an integer.            */           function getLineHeight(elem) {             var lh = computeStyle(elem, 'line-height');             if (lh == 'normal') {               // Normal line heights vary from browser to browser. The spec recommends               // a value between 1.0 and 1.2 of the font size. Using 1.1 to split the diff.               lh = parseInt(computeStyle(elem, 'font-size')) * 1.2;             }             return parseInt(lh);           }                         // MEAT AND POTATOES (MMMM, POTATOES...) ______________________________________           var splitOnChars = opt.splitOnChars.slice(0),             splitChar = splitOnChars[0],             chunks,             lastChunk;                  /**            * Gets an element's last child. That may be another node or a node's contents.            */           function getLastChild(elem) {             //Current element has children, need to go deeper and get last child as a text node             if (elem.lastChild.children && elem.lastChild.children.length > 0) {               return getLastChild(Array.prototype.slice.call(elem.children).pop());             }             //This is the absolute last child, a text node, but something's wrong with it. Remove it and keep trying             else if (!elem.lastChild || !elem.lastChild.nodeValue || elem.lastChild.nodeValue === '' || elem.lastChild.nodeValue == opt.truncationChar) {               elem.lastChild.parentNode.removeChild(elem.lastChild);               return getLastChild(element);             }             //This is the last child we want, return it             else {               return elem.lastChild;             }           }                  /**            * Removes one character at a time from the text until its width or            * height is beneath the passed-in max param.            */           function truncate(target, maxHeight) {             if (!maxHeight) {               return;             }                    /**              * Resets global variables.              */             function reset() {               splitOnChars = opt.splitOnChars.slice(0);               splitChar = splitOnChars[0];               chunks = null;               lastChunk = null;             }                    var nodeValue = target.nodeValue.replace(opt.truncationChar, '');                    //Grab the next chunks             if (!chunks) {               //If there are more characters to try, grab the next one               if (splitOnChars.length > 0) {                 splitChar = splitOnChars.shift();               }               //No characters to chunk by. Go character-by-character               else {                 splitChar = '';               }                      chunks = nodeValue.split(splitChar);             }                    //If there are chunks left to remove, remove the last one and see if             // the nodeValue fits.             if (chunks.length > 1) {               // console.log('chunks', chunks);               lastChunk = chunks.pop();               // console.log('lastChunk', lastChunk);               applyEllipsis(target, chunks.join(splitChar));             }             //No more chunks can be removed using this character             else {               chunks = null;             }                    //Insert the custom HTML before the truncation character             if (truncationHTMLContainer) {               target.nodeValue = target.nodeValue.replace(opt.truncationChar, '');               element.innerHTML = target.nodeValue + ' ' + truncationHTMLContainer.innerHTML + opt.truncationChar;             }                    //Search produced valid chunks             if (chunks) {               //It fits               if (element.clientHeight <= maxHeight) {                 //There's still more characters to try splitting on, not quite done yet                 if (splitOnChars.length >= 0 && splitChar !== '') {                   applyEllipsis(target, chunks.join(splitChar) + splitChar + lastChunk);                   chunks = null;                 }                 //Finished!                 else {                   return element.innerHTML;                 }               }             }             //No valid chunks produced             else {               //No valid chunks even when splitting by letter, time to move               //on to the next node               if (splitChar === '') {                 applyEllipsis(target, '');                 target = getLastChild(element);                        reset();               }             }                    //If you get here it means still too big, let's keep truncating             if (opt.animate) {               setTimeout(function() {                 truncate(target, maxHeight);               }, opt.animate === true ? 10 : opt.animate);             } else {               return truncate(target, maxHeight);             }           }                  function applyEllipsis(elem, str) {             elem.nodeValue = str + opt.truncationChar;           }                         // CONSTRUCTOR ________________________________________________________________                  if (clampValue == 'auto') {             clampValue = getMaxLines();           } else if (isCSSValue) {             clampValue = getMaxLines(parseInt(clampValue));           }                  var clampedText;           if (supportsNativeClamp && opt.useNativeClamp) {             sty.overflow = 'hidden';             sty.textOverflow = 'ellipsis';             sty.webkitBoxOrient = 'vertical';             sty.display = '-webkit-box';             sty.webkitLineClamp = clampValue;                    if (isCSSValue) {               sty.height = opt.clamp + 'px';             }           } else {             var height = getMaxHeight(clampValue);             if (height <= element.clientHeight) {               console.log(getLastChild(element));               clampedText = truncate(getLastChild(element), height);             }           }                  return {             'original': originalText,             'clamped': clampedText           };         }         clamp(el,{clamp: 2})      } })

其实很简单,仅仅是把clamp.js中的函数搬移了过来。然后就可以像这样来使用:

  <div class="txt" v-clamp>很抱歉!没有搜索到相关模板很抱歉!没有搜索到相关模板很抱歉!没有搜索到相关模板很抱歉!没有搜索到相关模板</div>
本文由(壳先生)整理自网络,如转载请注明出处:https://www.mrshell.com;
本站发布的内容若侵犯到您的权益,请邮件联系 i@mrshell.com 删除,我们将及时处理!
===========================================================================

1. 本站大部分下载资源收集于网络,不保证其完整性以及安全性,请下载后自行测试。
2. 本站资源仅供学习和交流使用,版权归资源原作者所有,请在下载后24小时之内自觉删除。
3. 不得使用于非法商业用途,商用请支持正版!不得违反国家法律,否则后果自负!
4. 若作商业用途,请购买正版,由于未及时购买和付费发生的侵权行为,与本站无关。
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!

=================================================================

壳先生 » 通过封装一个v-clamp的指令处理多行文本的溢出

发表评论

提供最优质的资源集合

立即查看 了解详情