slate 系列 - 不同空格的处理

slate 的数据在最终渲染到页面后会出现问题,表现为行首空格消失,文字之间的多个空格变成一个空格。而一般的 div contenteditable 中的空格可以连续渲染。

对于这个问题有几个概念先解释一下

  1. 前端编码过程中常见的空格包括这两个: &nbsp 和由键盘 space 键打出的空格(unicode 分别表示为 \u00a0\u0020),区别在于如图所示红框区域,前者被称之为不可换行空格open in new window,所以在图中出现折行的位置,10 km 是直接一起换行而不像蓝框中会在 10km 之间折行。 图一
  2. 浏览器本身对于由键盘 space 键打出的空格的处理方式如上图,浏览器会自动合并多个连续的空白字符,对于开头的空白字符,也不会渲染出来。在使用 innerText 和 innerHTML 看出区分如图。 图二
  3. div 的 contenteditable 属性会在输入空格时做如视频open in new window中的效果(Chrome),会依次插入 \u0020\u00a0,保证了浏览器可以正确渲染出所有空格。

以上例子中的代码参考open in new window

解释了上面的概念之后再看问题: div contenteditable 中连续空格在上面第三点中解释了。slate 本身由数据渲染,最终储存的数据中的连续空格不会做特殊处理,就是单纯的连 \u0020。当最终渲染成页面时就会发生上面说的第二种情况,为避免这种情况,我们可以在 slate 中可以在最终保存的数据做二次处理,处理方式可以是比如

text = text.replace(/\u0020{2,}/g, (str) => {
  const len = str.length;
  let space = '';
  for (let i = 0; i < len; i++) {
    space += i % 2 === 0 ? '\u00a0' : '\u0020';
  }
  return space;
});

通过这种方式在保存之前将 slate json 数据中的 text 做一次处理转成如上面视频中的那样。

上一篇 slate 系列 - 零宽空格在 slate 中的运用

Last Updated:
Contributors: YasinChan