uniapp 防止长表单数据丢失方案,缓存表单填写内容,放置卡退或误操作返回。

防止长表单数据丢失方案,缓存表单填写内容,放置卡退或误操作返回。

一、存储方案(多端兼容)

1. 使用 UniApp 的数据存储 API

javascript 复制代码
// utils/storage.js
export class FormDraftManager {
  constructor(formKey = 'formDraft') {
    this.formKey = formKey;
  }
  
  // 保存草稿
  saveDraft(formData) {
    const draft = {
      data: formData,
      timestamp: Date.now(),
      formVersion: '1.0'
    };
    
    try {
      uni.setStorageSync(this.formKey, draft);
      return true;
    } catch (e) {
      console.error('保存草稿失败:', e);
      return false;
    }
  }
  
  // 获取草稿
  getDraft() {
    try {
      return uni.getStorageSync(this.formKey);
    } catch (e) {
      console.error('读取草稿失败:', e);
      return null;
    }
  }
  
  // 清除草稿
  clearDraft() {
    try {
      uni.removeStorageSync(this.formKey);
      return true;
    } catch (e) {
      console.error('清除草稿失败:', e);
      return false;
    }
  }
  
  // 检查草稿是否有效(例如24小时内)
  isDraftValid(draft, maxAge = 24 * 60 * 60 * 1000) {
    if (!draft || !draft.timestamp) return false;
    return (Date.now() - draft.timestamp) < maxAge;
  }
}

二、恢复确认弹窗实现

1. 使用 UniApp 的模态框 API

javascript 复制代码
// pages/your-form-page.vue
<script>
import { FormDraftManager } from '@/utils/storage.js';

export default {
  data() {
    return {
      formData: {
        name: '',
        email: '',
        phone: '',
        // ...其他表单字段
      },
      draftManager: new FormDraftManager(),
      hasRecovered: false
    }
  },
  
  onLoad() {
    this.checkAndRecoverDraft();
  },
  
  onUnload() {
    // 页面卸载时自动保存(可选)
    this.autoSaveDraft();
  },
  
  methods: {
    // 检查并恢复草稿
    async checkAndRecoverDraft() {
      const draft = this.draftManager.getDraft();
      
      if (this.draftManager.isDraftValid(draft)) {
        // 显示恢复确认弹窗
        this.showRecoveryConfirm(draft);
      }
    },
    
    // 显示恢复确认弹窗
    showRecoveryConfirm(draft) {
      const formattedTime = this.formatTime(draft.timestamp);
      
      uni.showModal({
        title: '恢复填写进度?',
        content: `检测到您上次在 ${formattedTime} 有未提交的表单内容,是否恢复?`,
        confirmText: '恢复数据',
        cancelText: '重新开始',
        confirmColor: '#007AFF',
        success: (res) => {
          if (res.confirm) {
            this.restoreFormData(draft.data);
          } else {
            this.clearDraft();
          }
        }
      });
    },
    
    // 恢复表单数据
    restoreFormData(draftData) {
      this.formData = { ...this.formData, ...draftData };
      this.hasRecovered = true;
      
      // 显示成功提示
      uni.showToast({
        title: '数据恢复成功',
        icon: 'success',
        duration: 2000
      });
    },
    
    // 自动保存草稿
    autoSaveDraft() {
      // 检查表单是否有内容
      if (this.hasFormData()) {
        this.draftManager.saveDraft(this.formData);
      }
    },
    
    // 检查表单是否有数据
    hasFormData() {
      return Object.values(this.formData).some(value => 
        value !== '' && value !== null && value !== undefined
      );
    },
    
    // 清除草稿
    clearDraft() {
      this.draftManager.clearDraft();
    },
    
    // 格式化时间
    formatTime(timestamp) {
      const date = new Date(timestamp);
      return `${date.getMonth() + 1}月${date.getDate()}日 ${date.getHours()}:${date.getMinutes().toString().padStart(2, '0')}`;
    },
    
    // 表单提交
    async submitForm() {
      try {
        // 你的提交逻辑
        // await submitApi(this.formData);
        
        // 提交成功后清除草稿
        this.clearDraft();
        
        uni.showToast({
          title: '提交成功',
          icon: 'success'
        });
        
      } catch (error) {
        uni.showToast({
          title: '提交失败',
          icon: 'error'
        });
      }
    },
    
    // 手动保存草稿(可提供给用户操作)
    manualSaveDraft() {
      if (this.draftManager.saveDraft(this.formData)) {
        uni.showToast({
          title: '草稿已保存',
          icon: 'success'
        });
      }
    }
  }
}
</script>

三、实时自动保存(增强体验)

1. 防抖自动保存

javascript 复制代码
// 在 data 中添加
data() {
  return {
    // ...其他数据
    autoSaveTimer: null
  }
},

// 在 methods 中添加
methods: {
  // 输入时触发自动保存(防抖)
  onInput(field, value) {
    this.formData[field] = value;
    this.debouncedAutoSave();
  },
  
  // 防抖自动保存
  debouncedAutoSave() {
    if (this.autoSaveTimer) {
      clearTimeout(this.autoSaveTimer);
    }
    
    this.autoSaveTimer = setTimeout(() => {
      this.autoSaveDraft();
    }, 2000); // 2秒后自动保存
  },
  
  // 显示保存状态
  showSaveStatus() {
    // 可以在模板中显示保存状态
    this.saveStatus = '保存中...';
    
    setTimeout(() => {
      this.saveStatus = '已保存';
      setTimeout(() => {
        this.saveStatus = '';
      }, 2000);
    }, 500);
  }
}

四、模板部分

javascript 复制代码
<template>
  <view class="form-container">
    <!-- 保存状态提示 -->
    <view v-if="saveStatus" class="save-status">
      {{ saveStatus }}
    </view>
    
    <form @submit="submitForm">
      <view class="form-item">
        <text class="label">姓名</text>
        <input 
          class="input" 
          v-model="formData.name" 
          @input="onInput('name', $event.detail.value)"
          placeholder="请输入姓名" 
        />
      </view>
      
      <view class="form-item">
        <text class="label">邮箱</text>
        <input 
          class="input" 
          v-model="formData.email" 
          @input="onInput('email', $event.detail.value)"
          placeholder="请输入邮箱" 
          type="email"
        />
      </view>
      
      <view class="form-item">
        <text class="label">电话</text>
        <input 
          class="input" 
          v-model="formData.phone" 
          @input="onInput('phone', $event.detail.value)"
          placeholder="请输入电话" 
          type="number"
        />
      </view>
      
      <!-- 更多表单项... -->
      
      <view class="form-actions">
        <button class="btn-save-draft" @click="manualSaveDraft" type="button">
          保存草稿
        </button>
        
        <button class="btn-submit" form-type="submit">
          提交表单
        </button>
      </view>
    </form>
  </view>
</template>

<style scoped>
.form-container {
  padding: 30rpx;
}

.save-status {
  text-align: center;
  color: #07c160;
  font-size: 24rpx;
  margin-bottom: 20rpx;
}

.form-item {
  margin-bottom: 40rpx;
}

.label {
  display: block;
  margin-bottom: 10rpx;
  font-weight: bold;
}

.input {
  border: 1px solid #ddd;
  border-radius: 8rpx;
  padding: 20rpx;
  font-size: 28rpx;
}

.form-actions {
  display: flex;
  gap: 20rpx;
  margin-top: 60rpx;
}

.btn-save-draft {
  flex: 1;
  background: #f8f9fa;
  color: #333;
}

.btn-submit {
  flex: 2;
  background: #007AFF;
  color: white;
}
</style>
相关推荐
孤狼warrior1 小时前
爬虫进阶 JS逆向基础超详细,解锁加密数据
javascript·爬虫
前端炒粉2 小时前
18.矩阵置零(原地算法)
javascript·线性代数·算法·矩阵
listhi5202 小时前
利用React Hooks简化状态管理
前端·javascript·react.js
一点一木2 小时前
🚀 2025 年 10 月 GitHub 十大热门项目排行榜 🔥
前端·人工智能·github
华仔啊2 小时前
这个Vue3旋转菜单组件让项目颜值提升200%!支持多种主题,拿来即用
前端·javascript·css
非凡ghost3 小时前
Adobe Lightroom安卓版(手机调色软件)绿色版
前端·windows·adobe·智能手机·软件需求
BestAns3 小时前
Postman 平替?这款轻量接口测试工具,本地运行 + 批量回归超实用!
前端
CsharpDev-奶豆哥3 小时前
JavaScript性能优化实战大纲
开发语言·javascript·性能优化
专注前端30年4 小时前
Webpack进阶玩法全解析(性能优化+高级配置)
前端·webpack·性能优化
00后程序员张4 小时前
如何提高 IPA 安全性 多工具组合打造可复用的 iOS 加固与反编译防护体系(IPA 安全 iOS 加固 无源码混淆 Ipa Guard 实战)
android·安全·ios·小程序·uni-app·iphone·webview