富文本编辑器的层级
- L0
- L1: 兼容性层面的优化, 自行实现 undo/redo 栈;
- L2: 移动端/国际化适配;
一个好的框架设计: 尽量少的提前做的假设限制!
L0
- 给元素上加上
contenteditable
属性 - 给选中元素执行
document.execCommand()
另外一种方法是内嵌 iframe, 并将其 designmode 属性设置为 true。(有跨域问题, 日后填坑)
Slate 框架
调试
可以使用 editor.value.toJSON()
打印 tree 结构, 便于调试;
slate 设计模式
- 兜底原则
normalizeNode
, 除指定节点外都走该 normalize 机制;
有序列表的设计
- 小圆点 + 数字作为一个结构;
- 点击有序列表, 当前节点的同级兄弟节点都会变为有序列表;
- 点击可以取消有序列表;
- 当在有序列表的节点建立兄弟节点或子节点时, 自动设置为有序列表;
- 子节点规则 1 —— 1.1 —— 1.1.1 —— 1.1.1.1;
- 当把某个子节点从有序节点变为无序节点时, 该节点的兄弟节点也变为无序; 该节点的子节点从 1 开始计数;
- 原则: 兄弟节点必须都为有序或无序, 子节点可以无序也可以有序;
结论:
- 因此对 selection 是不敏感的, 即操作一个都会同时对同层级所有节点生效;
slate 开发坑点
- 一种方式开发完之后, 在某些情况下是不满足的, 因此需要返工。
- example: 输入 @、# 进行筛选最初是使用 set 方式实现的, 一开始这样设计是没问题的, 但是考虑未来在多人协作过程中会造成一份数据的互相影响, 因此将其重构调整为将筛选的数据绕开 set 的方式, 取而代之的是外面传递进来。
small tip
small tip in slate editor
When input b after a in page #slate #editor.
console.log(editor.value.texts.get(0))
requestAnimationFrame(() => {
console.log(editor.value.texts.get(0))
})
Web Excel
- Google Sheets
- Office 365
- WPS Web
- 钉钉表格
- 可扩展的表格
- 协同的表格
- 名词
- cp(Check Point): 全量表格数据
- op(Operation): 单次操作的表达
- OT(Operation Transform) 是协同算法的关键。
- 上限更高的 COT 调度算法要求 OT 同时运行在服务端与客户端
- Rust + WASM 实现 OT, 已验证最小闭环
- 高性能的表格
- 选择 canvas 渲染表格主界面, 不用 DOM 的原因是浪费在 DOM Pipeline 的开销很大
- 分层渲染管线
- 双缓冲画布, 支持流畅的滚动
- 自研排版引擎
协同编辑
link