邮件草稿自动保存器hooks代码实现
邮件草稿自动保存器hooks代码实现
基于之前的自动保存草稿设计思路——邮件项目草稿存取优化实践,做了初步的代码实现,将其封装成hooks,其功能主要就是草稿自动保存器。
设计回顾
其中比较编辑邮件是否发生变化的数据来源需要依赖业务组件传递
hooks说明
入参
业务组件需要传递hooks两个参数
1.如何拿到正在编辑有的信息的方法
getEditingData
2.调用保存草稿接口的方法
saveDraft
,该方法需要返回保存的草稿信息(即保存草稿接口入参)
返回结果
1+2.鉴于hooks需要能在正在提交草稿、取消草稿后自行关闭定时器,所以需要业务组件使用经hooks包装过的提交草稿(
saveDraftMailProcess
)、取消草稿方法(cancelMailDraftProcess
)。3.启动草稿自动保存器的入口
initAutoSaver
4.暴露编辑邮件是否发生变化的方法
isEmailContentEdited
5.暴露出缓存的草稿信息
cachedEmailRef
代码实现
import React, { useEffect, useRef } from 'react';
import EmailService from 'views/mail/utils/email.service';
import { isDataEquals } from 'views/mail/utils';
export const useAutoSave = (getEditingData, saveDraft) => {
const cachedEmailRef = useRef({});
const timeIdRef = useRef(null); // 定时器id
const saveProcessRef = useRef(null); // 自动保存
function isEmailContentEdited() {
const editingEmail = getEditingData();
editingEmail.content = editingEmail.rawContent;
return !isDataEquals(editingEmail, cachedEmailRef.current, ['subject', 'content', 'targets', 'targetsAddress', 'ccTargets', 'ccTargetsAddress', 'bccTargets', 'bccTargetsAddress', 'attachmentInfos']);
}
function initAutoSaver() {
// 强制首次必须保存,newestEmail直接传空即可
updateCachedFromServer({});
autoSave(true);
}
function updateCachedAfterSave() {
saveDraft().then((draft) => {
updateCachedFromServer(draft);
});
}
function updateCachedFromServer(newestEmail = {}) {
console.log('autosave updateCachedFromServer ~ ', newestEmail);
// 记录更新值
const cachedEmail = {};
fillEmailItems(cachedEmail, newestEmail);
cachedEmailRef.current = {
...cachedEmail,
content: newestEmail.rawContent || newestEmail.content,
};
console.log('autoSave updateCachedFromServer~ ', cachedEmailRef.current);
}
function cancelMailDraftProcess(params) {
saveProcessRef.current = true;
updateTimeId(null);
return EmailService.cancelDraftMail(params).then(res => {
saveProcessRef.current = false;
return res;
});
}
function saveDraftMailProcess(params) {
saveProcessRef.current = true;
return EmailService.saveDraftMail(params).then(res => {
saveProcessRef.current = false;
return res;
});
}
function autoSave(isInitial) {
const id = setTimeout(() => {
const isEmailEdited = isEmailContentEdited();
console.log('autoSave isEmailContentEdited -> ',isInitial, isEmailEdited, !saveProcessRef.current, new Date());
// 1.初始化 2.内容变化且当前不在提交中
if (isInitial || (isEmailEdited && !saveProcessRef.current)) {
updateCachedAfterSave(isInitial);
}
autoSave(false);
}, 10000);
updateTimeId(id);
}
function updateTimeId(id) {
// 根据日志测试下是否按照预期销毁了上个定时器
console.log('autoSave ~ ','clear: ', timeIdRef.current, 'new: ', id);
clearTimeout(timeIdRef.current);
timeIdRef.current = id;
}
// 只填充邮件对比相关字段信息
function fillEmailItems(target, source) {
['subject', 'content', 'sender', 'senderAddress', 'targets', 'targetsAddress', 'ccTargets', 'ccTargetsAddress', 'bccTargets', 'bccTargetsAddress', 'attachmentInfos'].forEach(item => {
target[item] = source[item];
});
return target;
}
// 当前页面销毁时及时销毁定时器
useEffect(() => {
return () => {
updateTimeId(null);
}
}, [])
return {
saveDraftMailProcess,
cancelMailDraftProcess,
initAutoSaver,
isEmailContentEdited,
cachedEmailRef,
}
}
- 分类:
- Web前端
相关文章
QQ邮箱、163邮箱自动保存草稿机制调研
背景 准备优化自己的邮箱项目中草稿的保存,目前是完全依赖调用后端接口保存,并且不支持自动保存功能,希望先调用主流邮箱的机制,并与之保持一致的用户体验。 QQ邮箱 页面切换时主体窗口内if 阅读更多…
webpack笔记——在html-webpack-plugin插件中提供给其它插件是使用的hooks
最近在这段时间刚好在温故下webpack源码,webpack5都出来了,4还不再学习下? 这次顺便学习下webpack的常用插件html-webpack-plugin。 发现这个插件里面还额外加入了 阅读更多…
转译:使用react hooks优化回调函数在组件间的传递,useState,useReducer?
我们先看一下使用 useState hooks写的todoList组件,里面我们需要层层传递回调函数。 import React, { useState } from "react& 阅读更多…
使用next.js服务端渲染经历
上周末的时候打算把自己的网站从vue的ssr转换为react的ssr,鉴于之前在vue中是用的原生的ssr,这次想在react中试试框架,所以首选的就是next.js。 第一次用next.js,根据 阅读更多…