最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

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

来源:动视网 责编:小采 时间:2020-11-27 19:29:25
文档

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

通过封装一个v-clamp的指令处理多行文本的溢出:本篇文章给大家带来的内容是关于通过封装一个v-clamp的指令处理多行文本的溢出,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。最近做项目时,遇到了一个需求:要求div里文本在两行显示,div的宽度是固定的,如果溢出的话就显示省略号。单
推荐度:
导读通过封装一个v-clamp的指令处理多行文本的溢出:本篇文章给大家带来的内容是关于通过封装一个v-clamp的指令处理多行文本的溢出,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。最近做项目时,遇到了一个需求:要求div里文本在两行显示,div的宽度是固定的,如果溢出的话就显示省略号。单


本篇文章给大家带来的内容是关于通过封装一个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>

文档

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

通过封装一个v-clamp的指令处理多行文本的溢出:本篇文章给大家带来的内容是关于通过封装一个v-clamp的指令处理多行文本的溢出,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。最近做项目时,遇到了一个需求:要求div里文本在两行显示,div的宽度是固定的,如果溢出的话就显示省略号。单
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top