我有一个组件,目前将呈现出如下所示的内容:
Corvid/游戏/魔兽世界/资产/角色模型/联盟/暗夜精灵/玛法里奥
我总是希望前两个项目和最后两个项目可见,但是,...如果可能的话,我希望中间的所有内容都截断.也就是说,如果上面的字符串要溢出包含div,它应该具有以下结果
Corvid/Games/.../暗夜精灵/玛法里奥
我尝试过如下结构:
<div className={styles.container}>
<div className={styles.first}>
{/** Contains first two items */}
</div>
<div className={styles.truncate}>
{/** N arbitrary path items */}
</div>
<div className={styles.last}>
{/** Last two items */}
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
这可以用CSS实现吗?
Bre*_*ody 11
有趣的问题 - 遗憾的是我无法看到可靠的CSS解决方案.也就是说,除非可以编辑HTML结构,即使这样会有一些硬编码,我也不相信有一个可靠的CSS解决方案.
但是,这里有3个可能的解决方案:
在下面的例子中,我创建了一个truncateBreadcrumbs()接受3个参数的函数:
selector - 与要截断的元素匹配的CSS选择器separator - 用于分隔元素的字符segments - 要将字符串截断为的段数它可以像:
truncateBreadcrumbs(".js-truncate", "/", 4);
Run Code Online (Sandbox Code Playgroud)
会找到所有带有类的元素.js-truncate并将内容截断为4个元素,...中间的分隔符,如:
Corvid / Games / ... / Night Elf / Malfurion
Run Code Online (Sandbox Code Playgroud)
也可以使用奇数段,例如5会产生:
Corvid / Games / World of Warcraft / ... / Night Elf / Malfurion
Run Code Online (Sandbox Code Playgroud)
如果segment参数等于或大于元素数,则不会发生截断.
这是完整的工作示例:
function truncateBreadcrumbs(selector, separator, segments) {
const els = Array.from(document.querySelectorAll(selector));
els.forEach(el => {
const split = Math.ceil(segments / 2);
const elContent = el.innerHTML.split(separator);
if (elContent.length <= segments) {
return;
}
el.innerHTML = [].concat(
elContent.slice(0, split),
["..."],
elContent.slice(-(segments-split))
).join(` ${separator} `);
});
}
truncateBreadcrumbs(".js-truncate--2", "/", 2);
truncateBreadcrumbs(".js-truncate--4", "/", 4);
truncateBreadcrumbs(".js-truncate--5", "/", 5);Run Code Online (Sandbox Code Playgroud)
<div class="js-truncate--2">Corvid / Games / World of Warcraft / Assets / Character Models / Alliance / Night Elf / Malfurion</div>
<div class="js-truncate--4">Corvid / Games / World of Warcraft / Assets / Character Models / Alliance / Night Elf / Malfurion</div>
<div class="js-truncate--5">Corvid / Games / World of Warcraft / Assets / Character Models / Alliance / Night Elf / Malfurion</div>
<div class="js-truncate--4">Corvid / Games / Night Elf / Malfurion</div>Run Code Online (Sandbox Code Playgroud)
它(根据className属性)显示您正在使用React.如果是这种情况,我们可以创建一个简单的功能组件来截断文本.我已经把上面的代码变成了一个功能组件<Truncate />,它做了同样的事情:
const Truncate = function(props) {
const { segments, separator } = props;
const split = Math.ceil(segments / 2);
const elContent = props.children.split(separator);
if (elContent.length <= segments) {
return (<div>{props.children}</div>);
}
const newContent = [].concat(
elContent.slice(0, split),
["..."],
elContent.slice(-(segments-split))
).join(` ${separator} `);
return (
<div>{newContent}</div>
)
}
Run Code Online (Sandbox Code Playgroud)
它可以用作:
<Truncate segments="4" separator="/">
Corvid / Games / World of Warcraft / Assets / Character Models / Alliance / Night Elf / Malfurion
</Truncate>
Run Code Online (Sandbox Code Playgroud)
这是完整的工作示例:
const Truncate = function(props) {
const { segments, separator } = props;
const split = Math.ceil(segments / 2);
const elContent = props.children.split(separator);
if (elContent.length <= segments) {
return (<div>{props.children}</div>);
}
const newContent = [].concat(
elContent.slice(0, split),
["..."],
elContent.slice(-(segments-split))
).join(` ${separator} `);
return (
<div>{newContent}</div>
)
}
class App extends React.Component {
render() {
return (
<div>
<Truncate segments="2" separator="/">
Corvid / Games / World of Warcraft / Assets / Character Models / Alliance / Night Elf / Malfurion
</Truncate>
<Truncate segments="4" separator="/">
Corvid / Games / World of Warcraft / Assets / Character Models / Alliance / Night Elf / Malfurion
</Truncate>
<Truncate segments="5" separator="/">
Corvid / Games / World of Warcraft / Assets / Character Models / Alliance / Night Elf / Malfurion
</Truncate>
<Truncate segments="4" separator="/">
Corvid / Games / Night Elf / Malfurion
</Truncate>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById("app"));Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>Run Code Online (Sandbox Code Playgroud)
我们还可以创建一个有状态的组件来响应屏幕/元素的宽度.这是一个非常粗略的想法 - 一个测试元素宽度并在必要时截断它的组件.理想情况下,组件只会根据需要截断,而不是截断到固定数量的段.
用法与上述相同:
<Truncate segments="4" separator="/">
Corvid / Games / World of Warcraft / Assets / Character Models / Alliance / Night Elf / Malfurion
</Truncate>
Run Code Online (Sandbox Code Playgroud)
但不同之处在于组件测试容器宽度以查看段是否适合,如果不是,则文本被截断.单击"展开代码段"按钮可全屏查看演示,以便您可以调整窗口大小.
class Truncate extends React.Component {
constructor(props) {
super(props);
this.segments = props.segments;
this.separator = props.separator;
this.split = Math.ceil(this.segments / 2);
this.state = {
content: props.children
}
}
componentDidMount = () => {
this.truncate();
window.addEventListener("resize", this.truncate);
}
componentWillUnmount = () => {
window.removeEventListener("resize", this.truncate);
}
truncate = () => {
if (this.div.scrollWidth > this.div.offsetWidth) {
const elContentArr = this.state.content.split(this.separator);
this.setState({
content: [].concat(
elContentArr.slice(0, this.split),
["..."],
elContentArr.slice(-(this.segments - this.split))
).join(` ${this.separator} `)
})
}
}
render() {
return (
<div className="truncate" ref={(el) => { this.div = el; }}>
{this.state.content}
</div>
)
}
}
class App extends React.Component {
render() {
return (
<div>
<Truncate segments="2" separator="/">
Corvid / Games / World of Warcraft / Assets / Character Models / Alliance / Night Elf / Malfurion
</Truncate>
<Truncate segments="4" separator="/">
Corvid / Games / World of Warcraft / Assets / Character Models / Alliance / Night Elf / Malfurion
</Truncate>
<Truncate segments="5" separator="/">
Corvid / Games / World of Warcraft / Assets / Character Models / Alliance / Night Elf / Malfurion
</Truncate>
<Truncate segments="4" separator="/">
Corvid / Games / Night Elf / Malfurion
</Truncate>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById("app"));Run Code Online (Sandbox Code Playgroud)
.truncate {
display: block;
overflow: visible;
white-space: nowrap;
}Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>Run Code Online (Sandbox Code Playgroud)
这是一种方法,只有总共超过4项时才有效.
ul { list-style-type: none; }
ul li { display: none; }
ul li:nth-last-child(n+2):after { content: " / "; }
ul li:nth-child(2):after { content: " / ... /"; }
ul li:nth-child(-n+2), ul li:nth-last-of-type(-n+2) { display: inline-block; }Run Code Online (Sandbox Code Playgroud)
<ul>
<li><a href="#">Corvid</a></li>
<li><a href="#">Games</a></li>
<li><a href="#">World of Warcraft</a></li>
<li><a href="#">Assets</a></li>
<li><a href="#">Character Models</a></li>
<li><a href="#">Alliance</a></li>
<li><a href="#">Night Elf</a></li>
<li><a href="#">Malfurion</a></li>
</ul>Run Code Online (Sandbox Code Playgroud)
解决这个问题的方法可能是在选择器前添加一个类,并且只有在超过4个项目时才会截断.理想情况下,这将添加到渲染上,但也可以通过javascript添加它,如本例所示
document.querySelectorAll("ul").forEach( el => el.childElementCount > 4 && el.classList.add("truncate") );Run Code Online (Sandbox Code Playgroud)
ul { list-style-type: none; }
ul li { display: inline-block;}
ul li:nth-last-child(n+2):after { content: " / "; }
ul.truncate li { display: none; }
ul.truncate li:nth-child(2):after { content: " / ... /"; }
ul.truncate li:nth-child(-n+2), ul li:nth-last-of-type(-n+2) { display: inline-block; }Run Code Online (Sandbox Code Playgroud)
<ul>
<li><a href="#">Corvid</a></li>
<li><a href="#">Games</a></li>
<li><a href="#">World of Warcraft</a></li>
<li><a href="#">Assets</a></li>
<li><a href="#">Character Models</a></li>
<li><a href="#">Alliance</a></li>
<li><a href="#">Night Elf</a></li>
<li><a href="#">Malfurion</a></li>
</ul>Run Code Online (Sandbox Code Playgroud)
不知道问题中是否有遗漏,但如果你不想改变你的结构,你也可以这样做:
.truncate div { display: inline-block; }
.truncate .mid { display: none; }
.truncate .first:after { content: "... /"; }Run Code Online (Sandbox Code Playgroud)
<div class="truncate">
<div class="first">
Corvid / Games /
</div>
<div class="mid">
World of Warcraft / Assets / Character Models / Alliance /
</div>
<div class="last">
Night Elf / Malfurion
</div>
</div>Run Code Online (Sandbox Code Playgroud)
或者如果你想要一个简单的纯js函数
document.querySelectorAll(".turncate").forEach( el => {
const parts = el.innerText.split(" / ");
if(parts.length > 4){
parts.splice(2, parts.length-4); //ensure we only have two first and last items
parts.splice(2, 0, "..."); // add ... after 2 first items.
el.innerText = parts.join(" / ");
}
});Run Code Online (Sandbox Code Playgroud)
<div class="turncate">
Corvid / Games / World of Warcraft / Assets / Character Models / Alliance / Night Elf / Malfurion
</div>Run Code Online (Sandbox Code Playgroud)