API

英文原地址

import * as Y from 'yjs'
1

共享类型

Y.Array

一种可共享的类数组类型,支持在任何位置插入/删除元素。在内部,它使用了数组链表,必要时可以分割数组。

const yarray = new Y.Array() 
1

insert(index:number, content:Array<object|boolean|Array|string|number|Uint8Array|Y.Type>)

index处插入内容。请注意内容是元素的数组。array.insert(0, [1])在索引0处拼接列表并插入1

push(Array<Object|boolean|Array|string|number|Uint8Array|Y.Type>)

unshift(Array<Object|boolean|Array|string|number|Uint8Array|Y.Type>)

delete(index:number, length:number)

get(index:number)

length:number

forEach(function(value:object|boolean|Array|string|number|Uint8Array|Y.Type, index:number, array: Y.Array))

map(function(T, number, YArray):M):Array<M>

toArray():Array<object|boolean|Array|string|number|Uint8Array|Y.Type>

将该YArray的内容拷贝到一个新数组中。

toJSON():Array<Object|boolean|Array|string|number>

将该YArray的内容拷贝到一个新数组中。该方法会使用toJSON方法将所有子类型转换为 JSON。

[Symbol.Iterator]

返回一个YArray迭代器,其中包含了数组中每个索引的值。

for (let value of yarray) { .. }

observe(function(YArrayEvent, Transaction):void)

向该类型添加一个事件侦听器,该事件侦听器将在每次修改这个类型时同步调用。如果在事件侦听器中修改了此类型,则在当前事件侦听器返回后将再次调用事件侦听器。

unobserve(function(YArrayEvent, Transaction):void)

从该类型中删除observe事件侦听器。

observeDeep(function(Array<YEvent>, Transaction):void)

向该类型添加一个事件侦听器,该事件侦听器将在每次修改此类型或其任何子类型时同步调用。如果在事件侦听器中修改了此类型,则在当前事件侦听器返回后将再次调用事件侦听器。事件侦听器接收自己或其子程序创建的所有事件。

unobserveDeep(function(Array<YEvent>, Transaction):void)

从该类型中删除observeDeep事件监听器。

Y.Map

共享 Map 类型。

const ymap = new Y.Map()
1

get(key:string):object|boolean|string|number|Uint8Array|Y.Type

set(key:string, value:object|boolean|string|number|Uint8Array|Y.Type)

delete(key:string)

has(key:string):boolean

get(index:number)

toJSON():Object<string, Object|boolean|Array|string|number|Uint8Array>

将该YMap[key,value]对复制到一个新对象。它使用toJSON方法将所有子类型转换为JSON。

forEach(function(value:object|boolean|Array|string|number|Uint8Array|Y.Type, key:string, map: Y.Map))

对每个键值对执行一次传入的函数。

[Symbol.Iterator]

返回迭代器的[key, value]对。

for (let [key, value] of ymap) { .. }
1

entries()

返回迭代器的[key, value]对。

values

返回迭代器的所有值。

keys

返回迭代器的所有键。

observe(function(YMapEvent, Transaction):void)

向该类型添加一个事件侦听器,该事件侦听器将在每次修改这个类型时同步调用。如果在事件侦听器中修改了此类型,则在当前事件侦听器返回后将再次调用事件侦听器。

unobserve(function(YMapEvent, Transaction):void)

从该类型中删除observe事件侦听器。

observeDeep(function(Array<YEvent>, Transaction):void)

向该类型添加一个事件侦听器,该事件侦听器将在每次修改此类型或其任何子类型时同步调用。如果在事件侦听器中修改了此类型,则在当前事件侦听器返回后将再次调用事件侦听器。事件侦听器接收自己或其子程序创建的所有事件。

unobserveDeep(function(Array<YEvent>, Transaction):void)

从该类型中删除observeDeep事件监听器。

Y.Text

为文本的共享编辑而优化的可共享类型。它允许在文本中将属性分配给范围。这让视线该类型的服务文绑定成为可能。

该类型还可以转换为delta format。同样地,YTextEvents计算增量变化。

const ytext = new Y.Text()
1

insert(index:number, content:string, [formattingAttributes:Object<string,string>])

index处插入一个字符串,并为其分配格式化属性。

ytext.insert(0, 'bold text', { bold: true })
1

delete(index:number, length:number)

format(index:number, length:number, formattingAttributes:Object<string,string>)

为文本中的的一定范围指定格式化属性。

applyDelta(delta, opts:Object<string,any>)

参见Quill Delta可以设置防止删除结束换行的配置项,默认为true

ytext.applyDelta(delta, { sanitize: false })
1

length:number

toString():string

在不使用格式化配置项的情况下,将此类型转换为字符串。

toJSON():string

参见toString

toDelta():Delta

将该类型转换为Quill Delta

observe(function(YTextEvent, Transaction):void)

向该类型添加一个事件侦听器,该事件侦听器将在每次修改这个类型时同步调用。如果在事件侦听器中修改了此类型,则在当前事件侦听器返回后将再次调用事件侦听器。

unobserve(function(YTextEvent, Transaction):void)

从该类型中删除observe事件侦听器。

observeDeep(function(Array<YEvent>, Transaction):void)

向该类型添加一个事件侦听器,该事件侦听器将在每次修改此类型或其任何子类型时同步调用。如果在事件侦听器中修改了此类型,则在当前事件侦听器返回后将再次调用事件侦听器。事件侦听器接收自己或其子程序创建的所有事件。

unobserveDeep(function(Array<YEvent>, Transaction):void)

从该类型中删除observeDeep事件监听器。

Y.XmlFragment

包含Y.XmlElements数组的容器。

const yxml = new Y.XmlFragment()
1

insert(index:number, content:Array<Y.XmlElement|Y.XmlText>)

delete(index:number, length:number)

get(index:number)

length:number

toArray():Array<Y.XmlElement|Y.XmlText>

将子元素拷贝到一个新数组。

toDOM():DocumentFragment

将此类型和所有子元素转换为新的 DOM 元素。

toString():string

获取所有后代的 XML 序列化。

toJSON():string

参见toString

observe(function(YXmlEvent, Transaction):void)

向该类型添加一个事件侦听器,该事件侦听器将在每次修改这个类型时同步调用。如果在事件侦听器中修改了此类型,则在当前事件侦听器返回后将再次调用事件侦听器。

unobserve(function(YXmlEvent, Transaction):void)

从该类型中删除observe事件侦听器。

observeDeep(function(Array<YEvent>, Transaction):void)

向该类型添加一个事件侦听器,该事件侦听器将在每次修改此类型或其任何子类型时同步调用。如果在事件侦听器中修改了此类型,则在当前事件侦听器返回后将再次调用事件侦听器。事件侦听器接收自己或其子程序创建的所有事件。

unobserveDeep(function(Array<YEvent>, Transaction):void)

从该类型中删除observeDeep事件监听器。

T.XmlElement

表示 XML 元素的可共享类型。它拥有nodeName、属性和一系列子节点。但是它不需要验证其内容,也不需要遵循 XML。

const yxml = new Y.XmlElement()
1

insert(index:number, content:Array<Y.XmlElement|Y.XmlText>)

delete(index:number, length:number)

get(index:number)

length:number

setAttribute(attributeName:string, attributeValue:string)

removeAttribute(attributeName:string)

getAttribute(attributeName:string):string

getAttributes(attributeName:string):Object<string,string>

toArray():Array<Y.XmlElement|Y.XmlText>

将子元素拷贝到一个新数组。

toDOM():Element

将此类型和所有子元素转换为新的 DOM 元素。

toString():string

获取所有后代的 XML 序列化。

toJSON():string

参见toString

observe(function(YXmlEvent, Transaction):void)

向该类型添加一个事件侦听器,该事件侦听器将在每次修改这个类型时同步调用。如果在事件侦听器中修改了此类型,则在当前事件侦听器返回后将再次调用事件侦听器。

unobserve(function(YXmlEvent, Transaction):void)

从该类型中删除observe事件侦听器。

observeDeep(function(Array<YEvent>, Transaction):void)

向该类型添加一个事件侦听器,该事件侦听器将在每次修改此类型或其任何子类型时同步调用。如果在事件侦听器中修改了此类型,则在当前事件侦听器返回后将再次调用事件侦听器。事件侦听器接收自己或其子程序创建的所有事件。

unobserveDeep(function(Array<YEvent>, Transaction):void)

从该类型中删除observeDeep事件监听器。

Y.Doc

const doc = new Y.Doc()
1

clientID readonly

表示客户的唯一ID。

gc

是否在该 doc 实例上启用了垃圾回收机制(Garbage Collection)。设置doc.gc = false以禁用垃圾回收并能够恢复旧内容。

transact(function(Transaction):void [, origin:any])

对共享文档的每个更改都发生在一个事件流程(transaction)中。观察者调用和更新事物是在每个事件流程后。您应该将更改放到单个事件流程中以降低事件调用的数量。举个例子,doc.transact(() => { yarray.insert(..); ymap.set(..) })触发单个的更改事件。

您可以通过设置可选参数origin,存储在transaction.originon('update', (update, origin) => ..)

toJSON():any

将整个文档转换为 js 对象,递归遍历每种 yjs 类型。

get(string, Y.[TypeClass]):[Type]

定义一个共享类型。

getArray(string):Y.Array

定义一个共享的 Y.Array 类型。等同于y.get(string, Y.Array)

getMap(string):Y.Map

定义一个共享的 Y.Map 类型。等同于y.get(string, Y.Map)

getXmlFragment(string):Y.XmlFragment

定义一个共享的 Y.XmlFragment 类型。等同于y.get(string, Y.XmlFragment)

on(string, function)

在共享类型上注册事件侦听器。

off(string, function)

解绑共享类型上的事件侦听器。

Y.Doc 事件

on('update', function(updateMessage:Uint8Array, origin:any, Y.Doc):void)

侦听文档更新。文档在更新时必须传输到所有其他的展示端。您可以不限顺序且多次的更新文档。

on('beforeTransaction', function(Y.Transaction, Y.Doc):void)

每个事件流程开始前派发。

on('afterTransaction', function(Y.Transaction, Y.Doc):void)

每个事件流程结束后派发。

on('beforeAllTransactions', function(Y.Doc):void)

事件流程可以嵌套(例如,在一个事件流程中调用另一个事件流程)。在首个事件流程前派发。

on('afterAllTransactions', function(Y.Doc, Array<Y.Transaction>):void)

在最后一个事件流程结束后派发。

文档更新

共享文档上的更改被编码到文档更新中。文档更新是可交换幂等的。这意味着它们可以以任何顺序应用且应用多次。

示例:侦听更新事件并将其应用于远程客户端

const doc1 = new Y.Doc()
const doc2 = new Y.Doc()

doc1.on('update', update => {
  Y.applyUpdate(doc2, update)
})

doc2.on('update', update => {
  Y.applyUpdate(doc1, update)
})

// 所有的更改也更新到了其他文档中
doc1.getArray('myarray').insert(0, ['Hello doc2, you got this?'])
doc2.getArray('myarray').get(0) // => 'Hello doc2, you got this?'
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Yjs 在内部维护了**“状态向量”(后面会介绍),用以表示每个客户端的下一个期望时钟。它保存了每个客户端创建的结构数量。当两个客户端同步时,您既可以交换完整的文档结构,也可以通过发送“状态向量”**来计算差异。

示例:通过交换完整的文档结构同步两个客户端

const state1 = Y.encodeStateAsUpdate(ydoc1)
const state2 = Y.encodeStateAsUpdate(ydoc2)
Y.applyUpdate(ydoc1, state2)
Y.applyUpdate(ydoc2, state1)
1
2
3
4

示例:通过计算差异同步两个客户端

这个例子展示了如何通过使用远程客户端的“状态向量”来计算差异,从而用最少的交换数据同步两个客户端。使用状态向量同步客户端需要另一次往返,但可以保证很大的带宽安全。

const stateVector1 = Y.encodeStateVector(ydoc1)
const stateVector2 = Y.encodeStateVector(ydoc2)
const diff1 = Y.encodeStateAsUpdate(ydoc1, stateVector2)
const diff2 = Y.encodeStateAsUpdate(ydoc2, stateVector1)
Y.applyUpdate(ydoc1, diff2)
Y.applyUpdate(ydoc2, diff1)
1
2
3
4
5
6

Y.applyUpdate(Y.Doc, update:Uint8Array, [transactionOrigin:any])

对共享文档应用更新。您可以选择设置transactionOrigin从而将其存储到transaction.Originydoc.on('update', (update, origin) => ..)

Y.encodeStateAsUpdate(Y.Doc, [encodedTargetStateVector:Uint8Array]):Uint8Array

将文档状态编码为可应用于远程文档的单个更新消息。可以选择指定目标状态向量,以便只将差异写入更新消息。

Y.encodeStateVector(Y.Doc):Uint8Array

计算状态向量并将其编码为 Uint8Array。

相对位置

警告

该API尚不稳定。

该特性用于管理选择的内容/光标。当和操作文档的其它用户一起工作时,请不要相信索引位置是你以为的位置。相对位置会始终保持在共享文档的元素上,不受远程更改的影响。举个例子,在文档中位置是“a|c”则相对位置就会判断到c。若远程用户在光标签插入了文档,光标仍旧会停留在c前。insert(1, 'x')("a|c") = "ax|c"。当相对位置设置为文档结尾,那么光标就会一直停留在文档结尾了。

示例:移动到相对位置并返回

const relPos = Y.createRelativePositionFromTypeIndex(ytext, 2)
const pos = Y.createAbsolutePositionFromRelativePosition(relPos, doc)
pos.type === ytext // => true
pos.index === 2 // => true
1
2
3
4

示例:向远程客户端发送相对位置(json)

const relPos = Y.createRelativePositionFromTypeIndex(ytext, 2)
const encodedRelPos = JSON.stringify(relPos)
// 向远程客户端发送 encodedRelPos。
const parsedRelPos = JSON.parse(encodedRelPos)
const pos = Y.createAbsolutePositionFromRelativePosition(parsedRelPos, remoteDoc)
pos.type === remoteytext // => true
pos.index === 2 // => true
1
2
3
4
5
6
7

示例:发送相对位置到远程客户端(Uint8Array)

const relPos = Y.createRelativePositionFromTypeIndex(ytext, 2)
const encodedRelPos = Y.encodeRelativePosition(relPos)
// 向远程客户端发送 encodedRelPos。
const parsedRelPos = Y.decodeRelativePosition(encodedRelPos)
const pos = Y.createAbsolutePositionFromRelativePosition(parsedRelPos, remoteDoc)
pos.type === remoteytext // => true
pos.index === 2 // => true
1
2
3
4
5
6
7

Y.createRelativePositionFromTypeIndex(Uint8Array|Y.Type, number)

Y.createAbsolutePositionFromRelativePosition(RelativePosition, Y.Doc)

Y.encodeRelativePosition(RelativePosition):Uint8Array

Y.decodeRelativePosition(Uint8Array):RelativePosition

Y.UndoManager

Yjs 自带了撤销/重做管理器,用以应对 Yjs 类型的撤销/重做。可以选择将更改的范围限定到起始事件流程。

const ytext = doc.getText('text')
const undoManager = new Y.UndoManager(ytext)

ytext.insert(0, 'abc')
undoManager.undo()
ytext.toString() // => ''
undoManager.redo()
ytext.toString() // => 'abc'
1
2
3
4
5
6
7
8

constructor(scope:Y.AbstractType|Array<Y.AbstractType> [, {captureTimeout:number,trackedOrigins:Set<any>,deleteFilter:function(item):boolean}])

可以接受单个类型作为范围,也可以接受类型数组。

undo()

redo()

stopCapturing()

on('stack-item-added', { stackItem: { meta: Map<any,any> }, type: 'undo' | 'redo' })

注册当StackItem添加到撤销栈或重做栈时调用的事件。

on('stack-item-popped', { stackItem: { meta: Map<any,any> }, type: 'undo' | 'redo' })

注册当StackItem从撤销栈或重做栈移出时调用的事件。

示例:停止捕获

如果创建的时间间隔小于options.captureTimeout,则UndoManager会合并Undo-StackItem。调用um.stopCapturing()可以避免下一个StackItem被合并。

// 无停止捕获
ytext.insert(0, 'a')
ytext.insert(1, 'b')
undoManager.undo()
ytext.toString() // => '' (注意 'ab' 被移除了)
// 带停止捕获
ytext.insert(0, 'a')
undoManager.stopCapturing()
ytext.insert(0, 'b')
undoManager.undo()
ytext.toString() // => 'a' (注意只有 'b' 被)
1
2
3
4
5
6
7
8
9
10
11

示例:指定追踪的起始点

共享文档上的每个更改都有一个起始点。如果没有指定起始点,则默认为null。通过指定trackedOrigins您可以有选择地指定UndoManager应该跟踪哪些更改。UndoManager实例总会被添加到trackedOrigins中。

class CustomBinding {}

const ytext = doc.getText('text')
const undoManager = new Y.UndoManager(ytext, {
  trackedOrigins: new Set([42, CustomBinding])
})

ytext.insert(0, 'abc')
undoManager.undo()
ytext.toString() // => 'abc' (不跟踪,因为起始点“null”并且不是“trackedTransactionOrigins”的一部分)
ytext.delete(0, 3) // 恢复

doc.transact(() => {
  ytext.insert(0, 'abc')
}, 42)
undoManager.undo()
ytext.toString() // => '' (跟踪,因为起始点是“trackedTransactionOrigins”的一部分)

doc.transact(() => {
  ytext.insert(0, 'abc')
}, 41)
undoManager.undo()
ytext.toString() // => '' (不跟踪,因为 41 不是“trackedTransactionOrigins”的一部分)
ytext.delete(0, 3) // 恢复

doc.transact(() => {
  ytext.insert(0, 'abc')
}, new CustomBinding())
undoManager.undo()
ytext.toString() // => '' (跟踪,因为起始点 `CustomBinding` 和 `CustomBinding`是 `trackedTransactionorigins`的一部分)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

示例:向StackItems添加其他信息

在撤消或重做以前的操作时,通常需要恢复其他元信息,如光标位置或文档上的视图。您可以为Undo-/Redo-StackItems分配元信息。

const ytext = doc.getText('text')
const undoManager = new Y.UndoManager(ytext, {
  trackedOrigins: new Set([42, CustomBinding])
})

undoManager.on('stack-item-added', event => {
  // 保存 stack-item 的当前光标位置
  event.stackItem.meta.set('cursor-location', getRelativeCursorLocation())
})

undoManager.on('stack-item-popped', event => {
  // 储存 stack-item 的当前光标位置
  restoreCursorLocation(event.stackItem.meta.get('cursor-location'))
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14