textarea的换行与空格问题

# 简介

# 各系统的换行问题 回车符\r和换行符\n

一、概念:

换行符‘\n’和回车符‘r’

(1)换行符就是另起一行 --- '\n' 10 换行(newline)

(2)回车符就是回到一行的开头 --- '\r' 13 回车(return)

所以我们平时编写文件的回车符应该确切来说叫做回车换行符

CR: 回车(Carriage Return) \r LF: 换行(Line Feed) \n

二、应用:

(1)在微软的MS-DOS和Windows中,使用“回车CR('\r')”和“换行LF('\n')”两个字符作为换行符;

(2)Windows系统里面,每行结尾是 回车+换行(CR+LF),即“\r\n”;

(3)Unix系统里,每行结尾只有 换行LF,即“\n”;

(4)Mac系统里,每行结尾是 回车CR 即'\r'。

Mac OS 9 以及之前的系统的换行符是 CR,从 Mac OS X (后来改名为“OS X”)开始的换行符是 LF即‘\n',和Unix/Linux统一了。

三、影响:

(1)一个直接后果是,Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;

(2)而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。

(3)Linux保存的文件在windows上用记事本看的话会出现黑点。

四、可以相互转换

在linux下,命令unix2dos 是把linux文件格式转换成windows文件格式,命令dos2unix 是把windows格式转换成linux文件格式。

在不同平台间使用FTP软件传送文件时, 在ascii文本模式传输模式下, 一些FTP客户端程序会自动对换行格式进行转换. 经过这种传输的文件字节数可能会发生变化.

如果你不想ftp修改原文件, 可以使用bin模式(二进制模式)传输文本。

一个程序在windows上运行就生成CR/LF换行格式的文本文件,而在Linux上运行就生成LF格式换行的文本文件。

# 空格显示不正常

这是因为浏览器显示机制,会将连续多个空格显示成1个空格。

在这些示例中,HTML和JSX中的空格是一样的
<div>Hello•World</div>
<div>•Hello•World</div>
<div>••Hello•World</div>
<div>•••Hello•World•••</div>
<div>Hello•••World</div>
123456
1
2
3
4
5
6
7

虽然JSX在在HTML中渲染多个空格,但是浏览器仍然会压缩空格序列。(假定CSS的white-space属性是默认值:normal)。

<div>
••Hello•World•••
</div>
// 开头和结尾处的空格被移除
<div>Hello•World</div>
12345
1
2
3
4
5
6

有两种解决方案:

  1. 使用&nbsp空格转义字符来添加空格;
  2. css样式设置为white-space:pre;

# 换行显示不正常

项目中遇到后台返回数据存在换行符却无法正常换行;比如:textarea元素中编辑带有格式的文本,无法按照原格式输出。举个例子,一个页面有textarea元素,一个div,一个按钮,当点击按钮时,将textarea中的值显示在div中。

<html>
<body>
    <textarea cols="10" rows="10"></textarea>
    <div></div>
    <button type="button">点击</button>
</body>
</html>
<script type="text/javascript">
   $('button').click(function(){
        $('div').html($('textarea').val());
   })
</script>
1
2
3
4
5
6
7
8
9
10
11
12

# 方式一:利用pre

1、在textarea输出的div中添加如下样式:

.content {   white-space: pre;}
1

2、利用

标签来输出textarea的内容:

<pre>这是textarea中的内容....</pre>
1

该方式的优缺点:

优点: 不需要区别浏览器, 正则校验替换, 保存输入的符号

缺点: 但是超出长度部分不会折行显示, 在同行显示, 需要添加 white-space的样式; 详见方法三;

white-space: pre-wrap || pre-line;
1

pre 标签样式, 可能会改变预期样式 字体大小, 颜色, 字体类型等, 需要全局设置初始值

# 方式二:将 \n\r 替换成 br 标签

利用正则,写法如下:

input.replace(/\r/ig, '').replace(/\n/ig, '<br/>')
1

注意: 需要 dangerouslySetInnerHTML: { __html: text} 解析。

该方式的优缺点:

优点: 可设置自动换行,可不修改样式, 如果统一处理包裹标签有可能会影响

缺点: dangerouslySetInnerHTML 有 XSS 漏洞, 建议使用 html escape 处理

import _ from 'lodash';
const createHtml = encodedHtml => ({
    __html: encoded(createHtml)
});
function encoded(html) {
    return _.escape(html).replace(/\r/g, '').replace(/\n/g, '<br/>')
}
export function newlineReplaceBr(input) {
    if (input) {
        return h.span({
            dangerouslySetInnerHTML: createHtml(input)
        })
    }
    else {
        return ''
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

使用JS字符串对象的方法replace

将textarea中所有的\n和\s分别替换成<br />&nbsp

<script type="text/javascript">
   $('button').click(function(){
 var new_str = $('textarea').val().replace(/\n|\r\n/g,'<br>').replace(/\s/g,'&nbsp;');
     $('div').html(new_str);
 })
</script>
//根据Value格式化为带有换行、空格格式的HTML代码
var getFormatCode=function(strValue){
    return strValue.replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' ');
}
1
2
3
4
5
6
7
8
9
10
 <div
          dangerouslySetInnerHTML={{
            __html: formatMessage({ id: 'JavaComponent.outputTips' }),
            // '(1)多条语句要用;号分开:<br />\n' +
            //  '(2)支持系统变量:如 SELECT * FROM table1 WHERE time=${time_id}<br />\n' +
            //  '(3)最后sql需要返回执行结果判断 (-1:执行失败,0:执行成功,1:重新等待)\n',
          }}
        />
1
2
3
4
5
6
7
8

# 方式三:在元素上white-space

所有浏览器都支持 white-space 属性。white-space 属性设置如何处理元素内的空白, 换行;

只需把CSS样式设置成white-space: pre-wrap;

  • pre-wrap 保留空白符序列,但是正常地进行换行
  • pre-line 合并空白符序列,但是保留换行符
  • pre: **空白会被浏览器保留, 在遇到换行符或者<br>**元素时才会换行, 类似 HTML 中的 <pre>标签

# white-space解释

white-space的值:

  • normal:连续的空白符会被合并,换行符会被当作空白符来处理。填充line盒子时,必要的话会换行。

  • nowrap:和 normal 一样,连续的空白符会被合并。但文本内的换行无效。

  • pre:连续的空白符会被保留。在遇到换行符或者<br>元素时才会换行。

  • pre-wrap连续的空白符会被保留。在遇到换行符或者<br>元素,或者需要为了填充line盒子时才会换行。

  • pre-line:连续的空白符会被合并。在遇到换行符或者<br>元素,或者需要为了填充line盒子时会换行。

white-space各个值的表现如下:

image-20201111205619111

.texty span {
  display: inline-block;
  white-space: pre-wrap;
}
1
2
3
4
是否能发挥作用 换行符 空格 自动换行 nbsp;
normal × ×(合并)
nowrap × ×(合并) ×
pre ×
pre-wrap
pre-line ×(合并)

# word-break、word-wrap、white-space的区别

  • white-space,控制空白字符的显示,同时还能控制是否自动换行。它有五个值:normal | nowrap | pre | pre-wrap | pre-line
  • word-break,控制单词如何被拆分换行。它有三个值:normal | break-all | keep-all
  • word-wrap(overflow-wrap)控制长度超过一行的单词是否被拆分换行,是word-break的补充,它有两个值:normal | break-word

# white-space

详见上面解释

# word-break

从这个名字可以知道,这个属性是控制单词如何被拆分换行的。它有三个值:normal | break-all | keep-all

word-break:keep-all

所有“单词”一律不拆分换行,注意,我这里的“单词”包括连续的中文字符(还有日文、韩文等),或者可以理解为只有空格可以触发自动换行

word-break:break-all

所有单词碰到边界一律拆分换行,不管你是incomprehensibilities这样一行都显示不下的单词,还是long这样很短的单词,只要碰到边界,都会被强制拆分换行。所以用word-break:break-all时要慎重呀。

# word-wrap(overflow-wrap)

word-wrap又叫做overflow-wrap

word-wrap 属性原本属于微软的一个私有属性,在 CSS3 现在的文本规范草案中已经被重名为 overflow-wrap 。 word-wrap 现在被当作 overflow-wrap 的 “别名”。 稳定的谷歌 Chrome 和 Opera 浏览器版本支持这种新语法。

这个属性也是控制单词如何被拆分换行的,实际上是作为word-break的互补,它只有两个值:normal | break-word

break-word

终于达到了上文我们希望的效果,只有当一个单词一整行都显示不下时,才会拆分换行该单词。 所以我觉得overflow-wrap更好理解好记一些,overflow,只有长到溢出的单词才会被强制拆分换行!

设置强行换行

无效的原因:元素中设置的white-space是norwrap,所以无法换行。

解决:

white-space:normal
word-wrap:break-word
1
2

# 参考链接

https://juejin.im/post/6844903667863126030

上次更新: 2022/04/15, 05:41:26
×