道招

邮件草稿自动保存器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,
  }
}
更新时间:
上一篇:华为手表(或手环)表盘主题制作下一篇:前端如何用一行代码将网站置灰

相关文章

转译:使用react hooks优化回调函数在组件间的传递,useState,useReducer?

我们先看一下使用 useState hooks写的todoList组件,里面我们需要层层传递回调函数。 import React, { useState } from "react& 阅读更多…

webpack笔记——在html-webpack-plugin插件中提供给其它插件是使用的hooks

最近在这段时间刚好在温故下webpack源码,webpack5都出来了,4还不再学习下? 这次顺便学习下webpack的常用插件html-webpack-plugin。 发现这个插件里面还额外加入了 阅读更多…

QQ邮箱、163邮箱自动保存草稿机制调研

背景 准备优化自己的邮箱项目中草稿的保存,目前是完全依赖调用后端接口保存,并且不支持自动保存功能,希望先调用主流邮箱的机制,并与之保持一致的用户体验。 QQ邮箱 页面切换时主体窗口内if 阅读更多…

使用next.js服务端渲染经历

上周末的时候打算把自己的网站从vue的ssr转换为react的ssr,鉴于之前在vue中是用的原生的ssr,这次想在react中试试框架,所以首选的就是next.js。 第一次用next.js,根据 阅读更多…

关注道招网公众帐号
友情链接
消息推送
道招网关注互联网,分享IT资讯,前沿科技、编程技术,是否允许文章更新后推送通知消息。
允许
不用了