人人做全免费网站,wordpress短代码图片,申请一个电子邮箱,自己的电脑做服务器 并建网站对于频繁改动的应用#xff0c;自动保存的功能是一个非常有用的功能#xff0c;可以避免用户在没有保存的情况下丢失自己保存过的数据。 对于自动保存#xff0c;一般有两种实现#xff0c;参考语雀和石墨#xff1a;
语雀采用的是定时保存的方式#xff0c;大约在3分半…对于频繁改动的应用自动保存的功能是一个非常有用的功能可以避免用户在没有保存的情况下丢失自己保存过的数据。 对于自动保存一般有两种实现参考语雀和石墨
语雀采用的是定时保存的方式大约在3分半后自动发送一次请求石墨文档采用的是实时保存对于文本区域直接输入字符的时候会发送请求就是在文本区域onchange的时候绑定一个事件有新内容介入的时候发送请求。
这里我们可以采用第一种方法定时发送请求。采用这种方式之前我们可以进行一个优化为了避免一股脑的发送请求比如说如果用户没有做任何操作到时候还是会发送请求所以呢我们要给他添加一个特殊字段isDirty这个字段可以标记一次数据是否有修改加入有修改才进行保存这里采用的方式和做历史数据功能的方式类似不会采用对比新旧数据比较耗时的方法而是触发特定的mutations才会标记字段比如说addComponent、deleteComponent、updateComponent、updatPage。
// 特殊字段
isDirty// 在一些 mutation 的时候同时修改该字段
addComponent
deleteComponent
updateComponent
updatePagestate.isDirty true// 在 save 之后将 isDirty 置为 false
state.isDirty false代码实现添加isDirty字段
// store/editor.ts
export interface EditorProps {// 供中间编辑器渲染的数组components: ComponentData[];// 当前编辑的是哪个元素uuidcurrentElement: string;// 当然最后保存的时候还有有一些项目信息这里并没有写出等做到的时候再补充page: PageData;// 当前被复制的组件copiedComponent?: ComponentData;// 当前操作的历史记录histories: HistoryProps[];// 当前历史记录的操作位置historyIndex: number;// 开始更新时的缓存值cachedOldValues: any;// 保存最多历史条目记录数maxHistoryNumber: number;// 数据是否有修改isDirty: boolean;
}然后在一系列mutations中给isDirty设置为true这都是一系列重复的功能这时候就想到之前使用过的高阶函数处理过浏览器的默认行为web架构师编辑器内容-快捷键操作的实现这里我们也可以封装成高阶函数来完成一系列操作比较方便
// store/editor.ts
const setDirtyWrapper (callback: MutationEditorProps) {return (state: EditorProps, payload: any) {state.isDirty true;callback(state, payload);};
};// mutations
// 添加元素
addComponent: setDirtyWrapper((state, component: ComponentData) {component.layerName 图层 (state.components.length 1);state.components.push(component);pushHistory(state, {id: uuidv4(),componentId: component.id,type: add,data: cloneDeep(component),});
})// 粘贴元素
pasteCopiedComponent: setDirtyWrapper((state) {if (state.copiedComponent) {const clone cloneDeep(state.copiedComponent);clone.id uuidv4();clone.layerName clone.layerName 副本;state.components.push(clone);message.success(已黏贴当前图层, 1);pushHistory(state, {id: uuidv4(),componentId: clone.id,type: add,data: cloneDeep(clone),});}
})// 删除元素
deleteComponent: setDirtyWrapper((state, id) {const currentComponent state.components.find((component) component.id id);if (currentComponent) {const currentIndex state.components.findIndex((component) component.id id);state.components state.components.filter((component) component.id ! id);pushHistory(state, {id: uuidv4(),componentId: currentComponent.id,type: delete,data: currentComponent,index: currentIndex,});message.success(删除当前图层成功, 1);}
})//更新元素
updateComponent: setDirtyWrapper((state, { key, value, id, isRoot }: UpdateComponentData) {const updatedComponent state.components.find((component) component.id (id || state.currentElement));if (updatedComponent) {if (isRoot) {(updatedComponent as any)[key as string] value;} else {const oldValue Array.isArray(key)? key.map((key) updatedComponent.props[key]): updatedComponent.props[key];if (!state.cachedOldValues) {state.cachedOldValues oldValue;}pushHistoryDebounce(state, { key, value, id });if (Array.isArray(key) Array.isArray(value)) {key.forEach((keyName, index) {updatedComponent.props[keyName] value[index];});} else if (typeof key string typeof value string) {updatedComponent.props[key] value;}}}}
)发送完请求后将isDirty置为false
// store/editor.ts
saveWork(state) {state.isDirty false;
},在onMounted生命周期里面增加对于的逻辑
onMounted(() {timer setInterval(() {if (isDirty.value) {saveWork();}}, 1000 * 50);
});
onUnmounted(() {clearInterval(timer);
});