#javascript #quill
#javascript #перо
Вопрос:
Я начал работать с Quill, и мне нужно сохранить изменения, внесенные пользователем в документе, и, если возможно, составить их, поэтому мне не нужно сохранять операцию за операцией.
Чтобы добиться этого, я отслеживаю событие «изменение текста», и каждая операция сохраняется в базе данных моего приложения. Время от времени (каждую минуту) я объединяю изменения, внесенные в документ, с предыдущим состоянием документа и выполняю различие между результатом этой композиции и предыдущим состоянием документа, сохраняя результат различия и удаляя предыдущие операции, потому что они находятся в результате различия.
Чтобы получить предыдущее состояние документа, изначально я использую исходный документ delta. Затем, когда разница сохранена, я просто составляю исходную дельту документа с различиями, которые существуют в базе данных. Например:
Дельта исходного документа: {"ops":[{"insert":"Evaluation Only. Created with Aspose.Words. Copyright 2003-2018 Aspose Pty Ltd.","attributes":{"size":"16px","font":"Calibri","bold":true,"color":"#FF0000"}},{"insert":"n","attributes":{"paragraph":true,"spacing_before":"0px","spacing_after":"10.67px","indent":0,"text_indent":"0px","line_spacing":"17.27px"}},{"insert":"Test","attributes":{"size":"14.67px","font":"Calibri","color":"#000000"}},{"insert":"s","attributes":{"size":"14.67px","font":"Calibri","color":"#000000"}},{"insert":"n","attributes":{"paragraph":true,"spacing_before":"0px","spacing_after":"10.67px","indent":0,"text_indent":"0px","line_spacing":"17.27px"}}],"page_setup":{"left_margin":"113.4px","top_margin":"94.47px","right_margin":"113.4px","bottom_margin":"94.47px"}}
Первое изменение: {"ops":[{"delete":80}]}
Второе изменение: {"ops":[{"retain":5},{"insert":"n","attributes":{"spacing_before":"0px","spacing_after":"10.67px","text_indent":"0px","line_spacing":"17.27px"}}]}
Третье изменение: {"ops":[{"retain":6},{"insert":"A","attributes":{"color":"#000000"}}]}
Код, который я использую, показан ниже:
var diffs = result.diffs;
var deltas = result.deltas;
var lastComposedDelta = null;
for (var i = 0; i < diffs.length; i ) {
var currentDelta = newDelta(diffs[i].Value);
if (lastComposedDelta == null) {
lastComposedDelta = currentDelta;
} else {
lastComposedDelta = lastComposedDelta.compose(currentDelta);
}
}
var composedDeltas = lastComposedDelta;
for (var i = 0; i < deltas.length; i ) {
var currentDelta = newDelta(deltas[i].Value);
if (composedDeltas == null) {
composedDeltas = currentDelta;
} else {
composedDeltas = composedDeltas.compose(currentDelta);
}
}
var diffDelta = composedDeltas;
if (lastComposedDelta != null) {
diffDelta = lastComposedDelta.diff(composedDeltas);
}
Результатом этого различия является: {"ops":[{"delete":80},{"retain":5},{"retain":1,"attributes":{"paragraph":null,"indent":null}},{"attributes":{"color":"#000000"},"insert":"A"},{"attributes":{"paragraph":true,"spacing_before":"0px","spacing_after":"10.67px","indent":0,"text_indent":"0px","line_spacing":"17.27px"},"insert":"n"}]}
Проблема, с которой я столкнулся, заключается в том, что пользователь вставляет новую строку и делает отступ, например. Дельта таких операций:
Новая строка: {"ops":[{"retain":8},{"insert":"n"}]}
Отступ: {"ops":[{"retain":9},{"retain":1,"attributes":{"indent":1}}]}
Затем, когда я пытаюсь изменить документ с помощью приведенного выше кода, он выдает ошибку:
Uncaught Error: diff() called with non-document
Значение «lastComposedDelta»: {"ops":[{"insert":"Tests","attributes":{"size":"14.67px","font":"Calibri","color":"#000000"}},{"insert":"n","attributes":{"spacing_before":"0px","spacing_after":"10.67px","text_indent":"0px","line_spacing":"17.27px"}},{"attributes":{"color":"#000000"},"insert":"A"},{"attributes":{"paragraph":true,"spacing_before":"0px","spacing_after":"10.67px","indent":0,"text_indent":"0px","line_spacing":"17.27px"},"insert":"n"},{"delete":80},{"retain":5},{"retain":1,"attributes":{"paragraph":null,"indent":null}},{"insert":"A","attributes":{"color":"#000000"}},{"insert":"n","attributes":{"paragraph":true,"spacing_before":"0px","spacing_after":"10.67px","indent":0,"text_indent":"0px","line_spacing":"17.27px"}}]}
Значение «composedDeltas»: {"ops":[{"insert":"Tests","attributes":{"size":"14.67px","font":"Calibri","color":"#000000"}},{"insert":"n","attributes":{"spacing_before":"0px","spacing_after":"10.67px","text_indent":"0px","line_spacing":"17.27px"}},{"insert":"A","attributes":{"color":"#000000"}},{"insert":"n","attributes":{"paragraph":true,"spacing_before":"0px","spacing_after":"10.67px","indent":0,"text_indent":"0px","line_spacing":"17.27px"}},{"insert":"n"},{"delete":80},{"retain":1,"attributes":{"indent":1}},{"retain":4},{"retain":1,"attributes":{"paragraph":null,"indent":null}},{"insert":"A","attributes":{"color":"#000000"}},{"insert":"n","attributes":{"paragraph":true,"spacing_before":"0px","spacing_after":"10.67px","indent":0,"text_indent":"0px","line_spacing":"17.27px"}}]}
Я немного покопался и обнаружил, что ошибка вызвана тем, что в дельтах, используемых для diff, выполняется операция «сохранить», и она не обрабатывается. Итак, я хочу знать, есть ли решение для этого, потому что я не уверен, что созданный мной код является правильным способом сделать это (сохранение различий в документе).
Ответ №1:
Если вам не нужна каждая отдельная операция, вы можете просто обновить документ по text-change
событию следующим образом:
quill.on('text-change', () => {
// By the time we hit the 'text-change' event,
// quill.getContents() will return the updated
// content of the document
const currentOps = quill.getContents();
updateDatabase(currentOps);
});
function updateDatabase(currentOps) {
// Do whatever you need to do with the current ops
// to store them. No need at all to store the diffs.
}
Ответ №2:
Итак, я обнаружил проблему с функцией diff. Это было потому, что, когда я инициализировал редактор, я использовал функцию updateContents
для установки разности, которая у меня была в базе данных, в редакторе. Quill всегда инициализирует редактор пустой строкой. Вызывая updateContents
, он составлял пустую строку с текстом, поступающим из моей базы данных. Затем, когда пользователь изменял текст, дельта из редактора отличалась от дельты в базе данных.
Чтобы исправить это, я изменил функцию, которая загружала содержимое из базы данных на setContents
. Таким образом, дельты из редактора и базы данных совпадали.