一陣做需求時(shí),有個(gè)小功能實(shí)現(xiàn)起來廢了點(diǎn)腦細(xì)胞,覺得可以記錄一下。
產(chǎn)品的具體訴求是:用戶點(diǎn)擊按鈕進(jìn)入詳情頁面,詳情頁內(nèi)的卡片標(biāo)題內(nèi)容過長時(shí),標(biāo)題的前后兩端正常展示,中間用省略號...表示,并且鼠標(biāo)懸浮后,展示全部內(nèi)容。
關(guān)于鼠標(biāo)懸浮展示全部內(nèi)容的代碼就不放在這里了,本文主要寫關(guān)于實(shí)現(xiàn)中間省略號...的代碼。
html代碼
<div class="title" id="test">近日,銀行紛紛下調(diào)大額存單利率,但銀行定期存款仍被瘋搶。銀行理財(cái)經(jīng)理表示:有意向購買定期存款要盡快,不確定利率是否會再降。</div>
css代碼: 設(shè)置文本不換行,同時(shí)設(shè)置overflow:hidden讓文本溢出盒子隱藏
.title {
width: 640px;
height: 40px;
line-height: 40px;
font-size: 14px;
color: #00b388;
border: 1px solid #ddd;
overflow: hidden;
/* text-overflow: ellipsis; */
white-space: nowrap;
/* box-sizing: border-box; */
padding: 0 10px;
}
javascript代碼:
獲取標(biāo)題盒子的寬度時(shí)要注意,如果在css樣式代碼中設(shè)置了padding, 就需要獲取標(biāo)題盒子的左右padding值。 通過getComputedStyle屬性獲取到所有的css樣式屬性對應(yīng)的值, 由于獲取的padding值都是帶具體像素單位的,比如: px,可以用parseInt特殊處理一下。
獲取盒子的寬度的代碼,我當(dāng)時(shí)開發(fā)時(shí)是用canvas計(jì)算的,但計(jì)算的效果不太理想,后來逛社區(qū),發(fā)現(xiàn)了嘉琪coder大佬分享的文章,我這里就直接把代碼搬過來用吧, 想了解的掘友可以直接滑到文章末尾查看。
判斷文本內(nèi)容是否超出標(biāo)題盒子
// 標(biāo)題盒子dom
const dom = document.getElementById('test');
// 獲取dom元素的padding值
function getPadding(el) {
const domCss = window.getComputedStyle(el, null);
const pl = Number.parseInt(domCss.paddingLeft, 10) || 0;
const pr = Number.parseInt(domCss.paddingRight, 10) || 0;
console.log('padding-left:', pl, 'padding-right:', pr);
return {
left: pl,
right: pr
}
}
// 檢測dom元素的寬度,
function checkLength(dom) {
// 創(chuàng)建一個(gè) Range 對象
const range = document.createRange();
// 設(shè)置選中文本的起始和結(jié)束位置
range.setStart(dom, 0),
range.setEnd(dom, dom.childNodes.length);
// 獲取元素在文檔中的位置和大小信息,這里直接獲取的元素的寬度
let rangeWidth = range.getBoundingClientRect().width;
// 獲取的寬度一般都會有多位小數(shù)點(diǎn),判斷如果小于0.001的就直接舍掉
const offsetWidth = rangeWidth - Math.floor(rangeWidth);
if (offsetWidth < 0.001) {
rangeWidth = Math.floor(rangeWidth);
}
// 獲取元素padding值
const { left, right } = getPadding(dom);
const paddingWidth = left + right;
// status:文本內(nèi)容是否超出標(biāo)題盒子;
// width: 標(biāo)題盒子真實(shí)能夠容納文本內(nèi)容的寬度
return {
status: paddingWidth + rangeWidth > dom.clientWidth,
width: dom.clientWidth - paddingWidth
};
}
通過charCodeAt返回指定位置的字符的Unicode編碼, 返回的值對應(yīng)ASCII碼表對應(yīng)的值,0-127包含了常用的英文、數(shù)字、符號等,這些都是占一個(gè)字節(jié)長度的字符,而大于127的為占兩個(gè)字節(jié)長度的字符。
截取和計(jì)算文本長度
js// 計(jì)算文本長度,當(dāng)長度之和大于等于dom元素的寬度后,返回當(dāng)前文字所在的索引,截取時(shí)會用到。
function calcTextLength(text, width) {
let realLength = 0;
let index = 0;
for (let i = 0; i < text.length; i++) {
charCode = text.charCodeAt(i);
if (charCode >= 0 && charCode <= 128) {
realLength += 1;
} else {
realLength += 2 * 14; // 14是字體大小
}
// 判斷長度,為true時(shí)終止循環(huán),記錄索引并返回
if (realLength >= width) {
index = i;
break;
}
}
return index;
}
// 設(shè)置文本內(nèi)容
function setTextContent(text) {
const { status, width } = checkLength(dom);
let str = '';
if (status) {
// 翻轉(zhuǎn)文本
let reverseStr = text.split('').reverse().join('');
// 計(jì)算左右兩邊文本要截取的字符索引
const leftTextIndex = calcTextLength(text, width);
const rightTextIndex = calcTextLength(reverseStr, width);
// 將右側(cè)字符先截取,后翻轉(zhuǎn)
reverseStr = reverseStr.substring(0, rightTextIndex);
reverseStr = reverseStr.split('').reverse().join('');
// 字符拼接
str = `${text.substring(0, leftTextIndex)}...${reverseStr}`;
} else {
str = text;
}
dom.innerHTML = str;
}
最終實(shí)現(xiàn)的效果如下:
上面就是此功能的所有代碼了,如果想要在本地試驗(yàn)的話,可以在本地新建一個(gè)html文件,復(fù)制上面代碼就可以了。
下面記錄下從社區(qū)內(nèi)學(xué)到的相關(guān)知識:
通過document.createRange和document.getBoundingClientRect()這兩個(gè)方法實(shí)現(xiàn)的。也就是我上面代碼中實(shí)現(xiàn)的checkLength方法。
通過創(chuàng)建一個(gè)不會在頁面顯示出來的dom元素,然后把文本內(nèi)容設(shè)置進(jìn)去,真實(shí)的文本長度與標(biāo)題盒子比較寬度,判斷是否被溢出隱藏了。
function getDomDivWidth(dom) {
const elementWidth = dom.clientWidth;
const tempElement = document.createElement('div');
const style = window.getComputedStyle(dom, null)
const { left, right } = getPadding(dom); // 這里我寫的有點(diǎn)重復(fù)了,可以優(yōu)化
tempElement.style.cssText = `
position: absolute;
top: -9999px;
left: -9999px;
white-space: nowrap;
padding-left:${style.paddingLeft};
padding-right:${style.paddingRight};
font-size: ${style.fontSize};
font-family: ${style.fontFamily};
font-weight: ${style.fontWeight};
letter-spacing: ${style.letterSpacing};
`;
tempElement.textContent = dom.textContent;
document.body.appendChild(tempElement);
const obj = {
status: tempElement.clientWidth + right + left > elementWidth,
width: elementWidth - left - right
}
document.body.removeChild(tempElement);
return obj;
}
這種方法是在UI框架acro design vue中實(shí)現(xiàn)的。外層套一個(gè)塊級(block)元素,內(nèi)部是一個(gè)行內(nèi)(inline)元素。給外層元素設(shè)置溢出隱藏的樣式屬性,不對內(nèi)層元素做處理,這樣內(nèi)層元素的寬度是不變的。因此,通過獲取內(nèi)層元素的寬度和外層元素的寬度作比較,就可以判斷出文本是否被溢出隱藏了。
// html代碼
<div class="title" id="test">
<span class="content">近日,銀行紛紛下調(diào)大額存單利率,但銀行定期存款仍被瘋搶。銀行理財(cái)經(jīng)理表示:有意向購買定期存款要盡快,不確定利率是否會再降。</span>
</div>
// 創(chuàng)建一個(gè)block元素來包裹inline元素
const content = document.querySelector('.content');
function getBlockDomWidth(dom) {
const { left, right } = getPadding(dom);
console.log(dom.clientWidth, content.clientWidth)
const obj = {
status: dom.clientWidth < content.clientWidth + left + right,
width: dom.clientWidth - left - right
}
return obj;
}
通過Canvas 2D渲染上下文(context)可以調(diào)用measureText方法,此方法會返回TextMetrics對象,該對象的width屬性值就是字符占據(jù)的寬度,由此也能獲取到文本的真實(shí)寬度,此方法有弊端,比如說兼容性,精確度等等。
// 獲取文本長度
function getTextWidth(text, font = 14) {
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d")
context.font = font
const metrics = context.measureText(text);
return metrics.width
}
通過charCodeAt獲取指定位置字符的Unicode編碼,返回的值對應(yīng)ASCII碼表對應(yīng)的值,0-127包含了常用的英文、數(shù)字、符號等,這些都是占一個(gè)字節(jié)長度的字符,而大于127的為占兩個(gè)字節(jié)長度的字符。
function calcTextLength(text) {
let realLength = 0;
for (let i = 0; i < text.length; i++) {
charCode = text.charCodeAt(i);
if (charCode >= 0 && charCode <= 128) {
realLength += 1;
} else {
realLength += 2;
}
}
return realLength;
}
function getTextWidth(text) {
return text.replace(/[^\x00-\xff]/g,"aa").length;
};
作者:娜個(gè)小部呀
鏈接:https://juejin.cn/post/7329967013923962895
文分享自華為云社區(qū)《JavaScript 里三個(gè)點(diǎn) ... 的用法-云社區(qū)-華為云》,作者: Jerry Wang 。
使用 rest 參數(shù),我們可以將任意數(shù)量的參數(shù)收集到一個(gè)數(shù)組中,然后用它們做我們想做的事情。引入了其余參數(shù)以減少由參數(shù)引起的樣板代碼。
function myFunc(a, b, ...args) {
console.log(a); // 22
console.log(b); // 98
console.log(args); // [43, 3, 26]
};
myFunc(22, 98, 43, 3, 26);
在 myFunc 的最后一個(gè)以 ...為前綴的參數(shù)中,這將導(dǎo)致所有剩余的參數(shù)都放在 javascript 數(shù)組中。
rest 參數(shù)收集所有剩余的參數(shù),因此在最后一個(gè)參數(shù)之前添加 rest 參數(shù)是沒有意義的。其余參數(shù)必須是最后一個(gè)形參。
rest 參數(shù)可以解構(gòu)(僅限數(shù)組),這意味著它們的數(shù)據(jù)可以解包為不同的變量。
function myFunc(...[x, y, z]) {
return x * y* z;
}
myFunc(1) // NaN
myFunc(1, 2, 3) // 6
myFunc(1, 2, 3, 4) // 6 (fourth parameter is not destructured)
展開運(yùn)算符用于將可迭代對象(如數(shù)組)的元素?cái)U(kuò)展到可以容納多個(gè)元素的位置。
function myFunc(x, y, ...params) { // used rest operator here
console.log(x);
console.log(y);
console.log(params);
}
var inputs = ["a", "b", "c", "d", "e", "f"];
myFunc(...inputs); // used spread operator here
// "a"
// "b"
// ["c", "d", "e", "f"]
一直有多種組合數(shù)組的方法,但是擴(kuò)展運(yùn)算符提供了一種用于組合數(shù)組的新方法:
const featured = ['Deep Dish', 'Pepperoni', 'Hawaiian'];
const specialty = ['Meatzza', 'Spicy Mama', 'Margherita'];
const pizzas = [...featured, 'veg pizza', ...specialty];
console.log(pizzas); // 'Deep Dish', 'Pepperoni', 'Hawaiian', 'veg pizza', 'Meatzza', 'Spicy Mama', 'Margherita'
使用擴(kuò)展運(yùn)算符,現(xiàn)在可以使用比 Object.assign() 更短的語法進(jìn)行淺克隆(不包括原型)或合并對象。
var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };
var clonedObj = { ...obj1 };
// Object { foo: "bar", x: 42 }
var mergedObj = { ...obj1, ...obj2 };
// Object { foo: "baz", x: 42, y: 13 }
當(dāng)我們在代碼中看到三個(gè)點(diǎn) (...) 時(shí),它要么是 rest 參數(shù),要么是展開運(yùn)算符。
有一個(gè)簡單的方法來區(qū)分它們:
點(diǎn)擊下方關(guān)注,第一時(shí)間了解華為云新鮮技術(shù)~
華為云博客_大數(shù)據(jù)博客_AI博客_云計(jì)算博客_開發(fā)者中心-華為云
置文字超長用省略號顯示的css代碼如下:
width:50px;overflow:hidden; white-space:nowrap; text-overflow:ellipsis;
但如果前面使用偽代碼設(shè)置了圖片,由于這里使用了
overflow:hidden;
很有可能圖片就顯示不出來了,此時(shí)解決方式可以是添加padding-left
padding-left: 20px
設(shè)置的左padding的寬度稍微大于偽代碼中設(shè)置的圖片的寬度
*請認(rèn)真填寫需求信息,我們會在24小時(shí)內(nèi)與您取得聯(lián)系。