손쉬운 협업 자바스크립트 스프레드시트 만들기
17044 단어 collabrationreactexcelwebdev
백엔드
주제에 들어가기 전에 가장 먼저 고려해야 할 사항은 백엔드 저장소입니다. 다른 사람이 페이지에 들어갈 때 최신 시트 상태를 볼 수 있도록 시트 데이터를 저장해야 하기 때문입니다.
Websocket은 클라이언트 간에 라이브 데이터를 교환하는 주요 전송 수단입니다. 여기서는 Express를 백엔드 서버로, MongoDB를 데이터베이스로 선택합니다. 익스프레스 서버의 주요 역할은 웹 소켓 연결을 관리하고 초기 데이터를 제공하며 증분
op
메시지를 처리하는 것입니다.이 데모에서는 컬렉션의 모든 문서를 데모 통합 문서의 시트로 사용합니다.
async function getData() {
const db = client.db(dbName);
return await db.collection(collectionName).find().toArray();
}
간단한 익스프레스 서버를 만드는 코드는 건너뛰고 핵심 코드에 집중하겠습니다. 걱정하지 마세요. 이 게시물의 끝에서 전체 코드를 찾을 수 있습니다.
그런 다음 websocket 메시지를 처리하기 위한 코드를 추가하고 브로드캐스팅을 위한 연결을 관리합니다.
const connections = {};
const broadcastToOthers = (selfId, data) => {
Object.values(connections).forEach((ws) => {
if (ws.id !== selfId) {
ws.send(data);
}
});
};
const wss = new SocketServer({ server, path: "/ws" });
wss.on("connection", (ws) => {
ws.id = uuid.v4();
connections[ws.id] = ws;
ws.on("message", async (data) => {
const msg = JSON.parse(data.toString());
if (msg.req === "getData") {
ws.send(
JSON.stringify({
req: msg.req,
data: await getData(),
})
);
} else if (msg.req === "op") {
await applyOp(client.db(dbName).collection(collectionName), msg.data);
broadcastToOthers(ws.id, data.toString());
}
});
ws.on("close", () => {
delete connections[ws.id];
});
});
여기서
applyOp
기능은 협업의 핵심입니다. 프론트엔드 라이브러리에서 보낸 Op
를 읽고 데이터베이스에 데이터 변형을 수행합니다.처리 작업
Op
는 Immer.js
의 패치에 의해 생성됩니다. 예를 들어 사용자가 셀 A2에서 셀 글꼴을 굵게 설정했을 때의 연산입니다.[
{
"op": "replace",
"index": "0",
"path": ["data", 1, 0, "bl"],
"value": 1
}
]
이 작업을 MongoDB 업데이트 쿼리로 변환해야 합니다. 직접 변환하면 결과는 다음과 같습니다.
db.updateOne(
{ index: "0" },
{ $set: { "data.1.0.bl": 1 } }
);
그러나 저장소 크기를 고려하여 셀 데이터를 데이터베이스에 드물게 저장합니다. 즉, 전체 2차원 셀 배열을 저장하는 대신 값을 포함하는 셀의 1차원 배열을 저장합니다. 따라서 데이터베이스의 셀은 다음과 같은 형식입니다.
{
r: number, // row index
c: number, // column index
v: any, // cell value
}
위의 업데이트 쿼리는 다음과 같습니다.
db.updateOne(
{ index: "0" },
{ $set: { "celldata.$[e].v.bl": 1 } },
{ arrayFilters: [{ "e.r": 1, "e.c": 0 }] }
);
시트의 다른 필드에 대한 업데이트도 비슷합니다.
이것이 우리 백엔드 서버의 전부입니다. 전체 코드는 https://github.com/ruilisi/fortune-sheet/tree/master/backend-demo을 참조하십시오.
프런트엔드
이제 프런트엔드 부분에 초점을 맞추겠습니다. 매우 간단합니다.
1단계, websocket 연결을 만듭니다.
const wsRef = useRef<WebSocket>();
useEffect(() => {
const socket = new WebSocket("ws://localhost:8081/ws");
wsRef.current = socket;
socket.onopen = () => {
socket.send(JSON.stringify({ req: "getData" }));
};
}, []);
2단계, 로컬 변경에서 op를 보내고 다른 사람으로부터 op를 받아 통합 문서에 적용합니다.
// A ref of Workbook
const workbookRef = useRef<WorkbookInstance>(null);
// In useEffect
socket.onmessage = (e) => {
const msg = JSON.parse(e.data);
if (msg.req === "getData") {
setData(msg.data);
} else if (msg.req === "op") {
workbookRef.current?.applyOp(msg.data);
}
};
// Workbook declaration
<Workbook
ref={workbookRef}
onOp={(op) => socket.send(JSON.stringify({ req: "op", data: op }))} />
전체 코드는 https://github.com/ruilisi/fortune-sheet/blob/master/stories/Collabration.stories.tsx을 참조하십시오.
읽어 주셔서 감사합니다
저장소는 완전히 오픈 소스인 Github에서 호스팅됩니다. 도움이 되셨다면 별표를 주세요 😄. 피드백은 대단히 감사합니다!
Reference
이 문제에 관하여(손쉬운 협업 자바스크립트 스프레드시트 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/zyc9012/creating-collabrative-javascript-spreadsheet-made-easy-3m9f텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)