5

邮件草稿自动保存器hooks代码实现

 1 year ago
source link: https://www.daozhao.com/10758.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

邮件草稿自动保存器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,
  }
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK