编辑器增加撤销、重做功能开发

This commit is contained in:
暮光:城中城
2020-06-14 22:24:35 +08:00
parent 39783b3467
commit 61f4c316d8
3 changed files with 36 additions and 23 deletions

View File

@@ -16,7 +16,7 @@
<template v-else-if="!!item.text">{{item.text}}</template>
<br v-else/>
</div>
<div v-else-if="item.type=='locate'" :class="item.cls" @click.stop="domClick(item, $event)">
<div v-else-if="item.type=='locate'" :class="item.cls" :index="index" @click.stop="domClick(item, $event)">
<br/>
</div>
</template>
@@ -91,7 +91,7 @@
this.userInput.addEventListener('keydown', e => {
if (e.which == 13) {
e.preventDefault();
this.editDom.keyEnter(this.editorDom, this.editorRange);
this.editDom.keyEnter(this.editorDom, this.editorRange, this.undoRedo);
} else if (e.keyCode == 90 && e.ctrlKey) {
e.preventDefault();
this.undoRedo.undo();
@@ -164,6 +164,7 @@
if (lastDom.type != 'locate') {
lastDom = new Dom('locate', 'locate');
this.editorDom.push(lastDom);
this.undoRedo.execute(2, this.editorDom.length - 1, JSON.stringify(lastDom), '');
}
setTimeout(() => event.target.lastChild.click(), 100);
},
@@ -220,10 +221,12 @@
userInputDataChange() {
if (!this.userInputData) return;
// 如果在最后一个div里面输入则改为非最后一个然后在最后再加一行
let domNew;
if (this.editDom.type == 'locate') {
this.editDom.type = 'text';
this.editDom.removeClass('locate');
this.editorDom.push(new Dom('locate', 'locate'));
domNew = new Dom('locate', 'locate');
this.editorDom.push(domNew);
}
let beforeJson = JSON.stringify(this.editDom);
let oldText = this.editDom.text || '';
@@ -244,6 +247,10 @@
let editDomNode = toolbarCommon.getRootDom(this.editDom.target);
let editIndex = parseInt(editDomNode.getAttribute("index"));
this.undoRedo.execute(1, editIndex, beforeJson, afterJson);
// 如果在最后一个div里面输入则改为非最后一个然后在最后再加一行
if (!!domNew) {
this.undoRedo.execute(2, this.editorDom.length - 1, JSON.stringify(domNew), '');
}
},
handleToolbarBold() {
for (let i = this.editorRange.startDomIndex; i < this.editorRange.endDomIndex; i++) {

View File

@@ -1,5 +1,6 @@
// 构造函数
import StyleRange from "./styleRange";
import toolbarCommon from "../../editor/toolbar/common";
function Dom(type = 'text', cls = '', text = '', styleRange = []) {
this.type = type;
@@ -128,20 +129,21 @@ Dom.prototype = {
}
},
// 回车事件处理
keyEnter(editorDom, editorRange) {
keyEnter(editorDom, editorRange, undoRedo) {
let nextText = '';
let oldText = this.text || '';
// 如果文字的中间位置点击,则把内容分割到两行
if (editorRange.startOffset < oldText.length) {
let beforeJson = JSON.stringify(this);
this.text = oldText.substring(0, editorRange.startOffset);
undoRedo.execute(1, editIndex, beforeJson, JSON.stringify(this));
nextText = oldText.substring(editorRange.startOffset, oldText.length);
}
for (let i = 0; i < editorDom.length; i++) {
if (this == editorDom[i]) {
editorDom.splice(i + 1, 0, new Dom('text', this.cls, nextText));
break;
}
}
let editDomNode = toolbarCommon.getRootDom(this.target);
let editIndex = parseInt(editDomNode.getAttribute("index"));
let domNew = new Dom('text', this.cls, nextText);
editorDom.splice(editIndex + 1, 0, domNew);
undoRedo.execute(2, editIndex + 1, JSON.stringify(domNew), '');
},
};

View File

@@ -2,6 +2,7 @@
import UndoInfo from "./undoInfo";
import Dom from "./dom";
import vue from '../../../main'
function UndoRedo(editorDom) {
this.editorDom = editorDom;
@@ -13,15 +14,19 @@ function UndoRedo(editorDom) {
UndoRedo.prototype = {
constructor: UndoRedo,
execute(type, index, before, after) {
// 最多保留20步
if (this.undoRedoList.length >= 20) {
// 忽略后面的操作步骤
if (this.undoRedoIndex >= 0 && this.undoRedoIndex < this.undoRedoList.length - 1) {
this.undoRedoList.splice(this.undoRedoIndex, this.undoRedoList.length - this.undoRedoIndex);
}
// 最多保留50步
if (this.undoRedoList.length >= 50) {
this.undoRedoList.splice(0, 1);
}
this.undoRedoList.push(new UndoInfo(type, index, before, after));
this.undoRedoIndex = this.undoRedoList.length - 1;
},
undo() {
if (this.undoRedoIndex < 0 || this.undoRedoIndex >= this.undoRedoList.length) {
if (this.undoRedoIndex >= this.undoRedoList.length) {
this.undoRedoIndex = this.undoRedoList.length - 1;
}
if (this.undoRedoIndex < 0) {
@@ -36,7 +41,7 @@ UndoRedo.prototype = {
} else {
this.undoObjDomToEditor(undoInfo, changeContent);
}
this.undoRedoIndex = Math.max(this.undoRedoIndex - 1, 0);
this.undoRedoIndex = Math.max(this.undoRedoIndex - 1, -1);
},
redo() {
this.undoRedoIndex++;
@@ -45,7 +50,8 @@ UndoRedo.prototype = {
return;
}
let undoInfo = this.undoRedoList[this.undoRedoIndex];
let changeContent = JSON.parse(undoInfo.after);
let actionText = (undoInfo.type == 1) ? undoInfo.after : undoInfo.before;
let changeContent = JSON.parse(actionText);
if (changeContent instanceof Array) {
changeContent.forEach(item => {
this.redoObjDomToEditor(undoInfo, item);
@@ -59,16 +65,14 @@ UndoRedo.prototype = {
if (undoInfo.type == 1) {
// 1=修改 2=添加 3=删除
if (this.editorDom.length > undoInfo.index) {
this.editorDom[undoInfo.index] = dom;
vue.$set(this.editorDom, undoInfo.index, dom);
}
} else if (undoInfo.type == 2) {
// 1=修改 2=添加 3=删除
if (this.editorDom.length > undoInfo.index) {
if (this.editorDom.length == undoInfo.index) {
this.editorDom.push(dom);
} else if (this.editorDom.length > undoInfo.index) {
this.editorDom.splice(undoInfo.index, 0, dom);
}
if (this.editorDom.length == undoInfo.index) {
this.editorDom.push(dom);
} else if (this.editorDom.length > undoInfo.index) {
this.editorDom.splice(undoInfo.index, 0, dom);
}
} else if (undoInfo.type == 3) {
// 1=修改 2=添加 3=删除
@@ -82,7 +86,7 @@ UndoRedo.prototype = {
if (undoInfo.type == 1) {
// 1=修改 2=添加 3=删除
if (this.editorDom.length > undoInfo.index) {
this.editorDom[undoInfo.index] = dom;
vue.$set(this.editorDom, undoInfo.index, dom);
}
} else if (undoInfo.type == 2) {
// 1=修改 2=添加 3=删除