web-sync-form
v1.0.1
Published
跨标签页存储表单数据
Readme
react 中使用
原生 form 组件使用
import { memo, useEffect, useRef, useState } from "react";
import { useNavigate } from "react-router";
import SyncForm from "../utils/index.ts";
const Page1 = memo(() => {
const [formData, setFormData] = useState({
username: "",
gender: "male",
});
const navigate = useNavigate();
const formStorage = useRef<SyncForm<"react">>(null);
// 不直接useRef( new SyncForm())是因为每次组件渲染SyncForm都会重新创建,
// 可能你会疑惑 useRef不是在整个生命周期只创建一次吗?
// 因为useRef传入的参数是一个函数
if (!formStorage.current) {
formStorage.current = new SyncForm(formData, {
type: "react",
formId: "page1Form",
setFormData,
delay: 1000,
});
}
const handleChange = (e: any) => {
const { name, value } = e.target;
setFormData((prevData) => {
const newValue = {
...prevData,
[name]: value,
};
// 广播新值
formStorage.current!.value = newValue;
formStorage.current!.debouncedSaveData();
return newValue;
});
};
useEffect(() => {
// 初始化表单数据 这样页面可以从缓存中读取数据
formStorage.current!.init();
}, []);
const nextPage = () => {
formStorage.current!.saveData();
navigate("/page2");
};
return (
<div className="container">
<h1>问题页1</h1>
<form id="page1Form">
<div>
<label htmlFor="username">您的姓名:</label>
<input
name="username"
type="text"
value={formData.username}
onChange={handleChange}
placeholder="请填写您的姓名"
/>
</div>
<div>
<label htmlFor="gender">您的性别:</label>
<select name="gender" value={formData.gender} onChange={handleChange}>
<option value="male">男</option>
<option value="female">女</option>
<option value="secret">保密</option>
</select>
</div>
<button className="single" type="button" onClick={nextPage}>
下一页
</button>
</form>
</div>
);
});
export default Page1;antd Form 组件使用
import React, { useEffect, useRef } from "react";
import type { FormProps } from "antd";
import { Button, Checkbox, Form, Input } from "antd";
import SyncForm from "../utils";
type FieldType = {
username?: string;
password?: string;
remember?: string;
};
const onFinishFailed: FormProps<FieldType>["onFinishFailed"] = (errorInfo) => {
console.log("Failed:", errorInfo);
};
const Page2: React.FC = () => {
const [form] = Form.useForm();
const formStorage = useRef<SyncForm<"react">>(null);
useEffect(() => {
formStorage.current!.init();
}, []);
if (!formStorage.current) {
formStorage.current = new SyncForm(form.getFieldsValue(), {
type: "react",
formId: "page2Form",
setFormData: form.setFieldsValue,
delay: 1000,
});
}
const handleValuesChange = (values: FieldType) => {
console.log(values);
formStorage.current!.value = values;
formStorage.current!.debouncedSaveData();
};
const onFinish: FormProps<FieldType>["onFinish"] = (values) => {
console.log("Success:", values);
SyncForm.clearAll();
};
return (
<Form
style={{ padding: 20 }}
form={form}
name="basic"
onFinish={onFinish}
onFinishFailed={onFinishFailed}
onValuesChange={handleValuesChange}
>
<Form.Item<FieldType>
label="Username"
name="username"
rules={[{ required: true, message: "Please input your username!" }]}
>
<Input />
</Form.Item>
<Form.Item<FieldType>
label="Password"
name="password"
rules={[{ required: true, message: "Please input your password!" }]}
>
<Input.Password />
</Form.Item>
<Form.Item<FieldType>
name="remember"
valuePropName="checked"
label={null}
>
<Checkbox>Remember me</Checkbox>
</Form.Item>
<Form.Item label={null}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
);
};
export default Page2;vue 使用
<template>
<div class="container">
<h1>问题页1</h1>
<form id="page1Form">
<div>
<label for="question1">您的姓名:</label>
<input
v-model="formData.username"
type="text"
name="question1"
placeholder="请填写您的姓名"
/>
</div>
<div>
<label for="question2">您的性别:</label>
<select name="question2" v-model="formData.gender">
<option value="male">男</option>
<option value="female">女</option>
<option value="secret">保密</option>
</select>
</div>
<button class="single" @click.prevent="nextPage">下一页</button>
</form>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, watch } from 'vue'
import { useRouter } from 'vue-router'
import FormStorage from '../utils/FormStorage'
import SyncForm from '@/utils/SyncForm'
const formData = ref({
username: '',
gender: 'secret'
})
const formStorage = new FormStorage('page1Form', formData)
const syncForm:SyncForm<'vue'> = new SyncForm(formData,{
formId:'page1Form1',
delay:1000,
type:'vue'
})
onMounted(() => {
syncForm.init()
})
watch(
formData,
() => {
console.log('ww')
syncForm.debouncedSaveData()
},
{ deep: true }
)
const router = useRouter()
const nextPage = () => {
// 切换路由之前先保存一下数据
syncForm.saveData()
router.push('/page2')
syncForm.clearData()
}
</script>
<style scoped>
.button-group {
display: flex;
justify-content: space-between;
}
</style>
