日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
用Yjs+React寫一個(gè)支持協(xié)同的TODO應(yīng)用

大家好,我是前端西瓜哥。

創(chuàng)新互聯(lián)公司服務(wù)項(xiàng)目包括新蔡網(wǎng)站建設(shè)、新蔡網(wǎng)站制作、新蔡網(wǎng)頁制作以及新蔡網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,新蔡網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到新蔡省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

為了測試 Yjs 的協(xié)同能力,我實(shí)現(xiàn)了支持協(xié)同簡單的 TODO 應(yīng)用。

支持的功能

  1. 創(chuàng)建房間;
  2. 新增、刪除、完成、清空所有待辦;
  3. 撤銷重做;
  4. 顯示其他用戶的光標(biāo)位置;

技術(shù)棧

列一下用到的技術(shù):

  1. Vite + React + TypeScript + React Router;
  2. Yjs、y-websocket:實(shí)現(xiàn)協(xié)同編輯;

源碼

源碼放 Github 上了。因?yàn)榛艘惶鞂懙暮喴?Demo,沒有太分模塊,代碼很稀爛,僅供參考。

https://github.com/F-star/yjs-react-todo-app。

運(yùn)行方式

先安裝依賴:

pnpm install

然后兩個(gè)終端分別啟動(dòng)服務(wù)端和客戶端:

pnpm run server
pnpm run dev

演示

簡單看看效果。

創(chuàng)建一個(gè)房間。

復(fù)制這個(gè)房間鏈接,在另一個(gè)瀏覽器里打開。

然后就是一段操作。

一些知識點(diǎn)

所有的需要同步的對象都保存在一個(gè) Y.Doc 對象下,在其下會(huì)創(chuàng)建 Yjs 的數(shù)據(jù)類型,比如 YArray、YMap。

this.ydoc = new Y.Doc();

然后我們需要一個(gè) Provider 去將這個(gè)對象的內(nèi)容同步出去,以及同步回來。

this.provider = new WebsocketProvider(wsUrl, this.roomId, this.ydoc);

模塊之間的解耦,果然還得是發(fā)布訂閱模式。通過 observer 監(jiān)聽數(shù)據(jù)的變化,然后同步到組件上。

// 創(chuàng)建頂層的 YArray 對象
this.yTodoItems = this.ydoc.getArray('todoItems');
this.yTodoItems.observe(callback);

// 拿到 YArray 對應(yīng)的普通數(shù)組對象,更新組件的內(nèi)部狀態(tài)
yjsClient.onTodoItemsChange((event) => {
  setTodoItems(event.target.toArray());
});

對于要修改一個(gè) YArray 下一個(gè)普通對象的情況,不能修改這個(gè)普通對象的屬性,它不會(huì)觸發(fā) observe 事件。我們有兩種解法。

第一種方案是從 YArray 對象下刪除對應(yīng)索引位置的對象,然后在這個(gè)地方再插入一個(gè)修改了屬性的拷貝對象。

toggleTodoItemDone(index: number) {
  // 下面的寫法無法觸發(fā) observe
  // const item = this.yTodoItems.get(index);
  // item.done = !item.done;

  // 下面的寫法可以觸發(fā) observe
  const item = this.yTodoItems.get(index);
  this.yTodoItems.delete(index, 1);
  this.yTodoItems.insert(index, [
    {
      id: item.id,
      text: item.text,
      done: !item.done,
    },
  ]);
}

第二種方案是可以將這個(gè)普通對象換成 Y.Map 對象嵌入 YArray 下,通過它的 API 修改屬性,然后用 YArray 的 observeDeep,不能再用 observe 了。

Yjs 的 TypeScript 類型支持不太完善。有些類型太寬泛,比如 YMap 只能定一個(gè)類似 Map 的類型,不能傳一個(gè)特定結(jié)構(gòu)的 interface,要自己用 as 手動(dòng)強(qiáng)轉(zhuǎn)類型。

另外,一些包的類型也無法使用,雖然我看到這個(gè)包下是有類型文件的。不知道是不是 vite 的問題。

結(jié)尾

Yjs 確實(shí)很強(qiáng)大,只要接上 Yjs 的數(shù)據(jù)結(jié)構(gòu)類型,就能快速實(shí)現(xiàn)一個(gè)分布式的協(xié)同編輯應(yīng)用。


名稱欄目:用Yjs+React寫一個(gè)支持協(xié)同的TODO應(yīng)用
轉(zhuǎn)載源于:http://m.5511xx.com/article/cdohjgh.html